New upstream version 3.1~rc1+ds1
authorRyan Pavlik <ryan@ryanpavlik.com>
Thu, 12 May 2022 21:57:12 +0000 (16:57 -0500)
committerRyan Pavlik <ryan@ryanpavlik.com>
Thu, 12 May 2022 21:57:12 +0000 (16:57 -0500)
406 files changed:
.github/ISSUE_TEMPLATE.md [new file with mode: 0644]
.github/scripts/build-macos.sh [new file with mode: 0755]
.github/scripts/build-snap.sh [new file with mode: 0755]
.github/scripts/build-ubuntu.sh [new file with mode: 0755]
.github/scripts/build-windows.sh [new file with mode: 0755]
.github/scripts/install-macos.sh [new file with mode: 0755]
.github/scripts/install-snap.sh [new file with mode: 0755]
.github/scripts/install-ubuntu.sh [new file with mode: 0755]
.github/scripts/install-windows.sh [new file with mode: 0755]
.github/scripts/sign-macos.sh [new file with mode: 0755]
.github/workflows/cd.yml [new file with mode: 0644]
.github/workflows/source-tarball.yml [new file with mode: 0644]
.github/workflows/test.yml [new file with mode: 0644]
CHANGELOG.md
CMakeLists.txt
CONTRIBUTING.md
README.md
cmake/FindSpaceWare.cmake
cmake/MacOSXBundleInfo.plist.in
cmake/libpng-macos-arm64.patch [new file with mode: 0644]
developer_docs/IdLists_Entities_and_Remap.txt [new file with mode: 0644]
developer_docs/Solver_Transforms.txt
extlib/mimalloc/.gitattributes [deleted file]
extlib/mimalloc/.gitignore [deleted file]
extlib/mimalloc/CMakeLists.txt
extlib/mimalloc/LICENSE
extlib/mimalloc/azure-pipelines.yml
extlib/mimalloc/bin/mimalloc-redirect.dll [new file with mode: 0644]
extlib/mimalloc/bin/mimalloc-redirect.lib [new file with mode: 0644]
extlib/mimalloc/bin/mimalloc-redirect32.dll [new file with mode: 0644]
extlib/mimalloc/bin/mimalloc-redirect32.lib [new file with mode: 0644]
extlib/mimalloc/bin/minject.exe [new file with mode: 0644]
extlib/mimalloc/bin/minject32.exe [new file with mode: 0644]
extlib/mimalloc/cmake/mimalloc-config-version.cmake
extlib/mimalloc/cmake/mimalloc-config.cmake
extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-1.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-2.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-spec-rss.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-spec.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-z4-1.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-z4-2.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-z4-rss-1.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2020/bench-z4-rss-2.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg [new file with mode: 0644]
extlib/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg [new file with mode: 0644]
extlib/mimalloc/doc/doxyfile [new file with mode: 0644]
extlib/mimalloc/doc/ds-logo.jpg [new file with mode: 0644]
extlib/mimalloc/doc/ds-logo.png [new file with mode: 0644]
extlib/mimalloc/doc/mimalloc-doc.h [new file with mode: 0644]
extlib/mimalloc/doc/mimalloc-doxygen.css [new file with mode: 0644]
extlib/mimalloc/doc/mimalloc-logo-100.png [new file with mode: 0644]
extlib/mimalloc/doc/mimalloc-logo.png [new file with mode: 0644]
extlib/mimalloc/doc/mimalloc-logo.svg [new file with mode: 0644]
extlib/mimalloc/doc/spades-logo.png [new file with mode: 0644]
extlib/mimalloc/doc/unreal-logo.svg [new file with mode: 0644]
extlib/mimalloc/docs/annotated.html [new file with mode: 0644]
extlib/mimalloc/docs/annotated_dup.js [new file with mode: 0644]
extlib/mimalloc/docs/bc_s.png [new file with mode: 0644]
extlib/mimalloc/docs/bdwn.png [new file with mode: 0644]
extlib/mimalloc/docs/bench.html [new file with mode: 0644]
extlib/mimalloc/docs/build.html [new file with mode: 0644]
extlib/mimalloc/docs/classes.html [new file with mode: 0644]
extlib/mimalloc/docs/closed.png [new file with mode: 0644]
extlib/mimalloc/docs/doc.png [new file with mode: 0644]
extlib/mimalloc/docs/doxygen.css [new file with mode: 0644]
extlib/mimalloc/docs/doxygen.png [new file with mode: 0644]
extlib/mimalloc/docs/dynsections.js [new file with mode: 0644]
extlib/mimalloc/docs/environment.html [new file with mode: 0644]
extlib/mimalloc/docs/folderclosed.png [new file with mode: 0644]
extlib/mimalloc/docs/folderopen.png [new file with mode: 0644]
extlib/mimalloc/docs/functions.html [new file with mode: 0644]
extlib/mimalloc/docs/functions_vars.html [new file with mode: 0644]
extlib/mimalloc/docs/group__aligned.html [new file with mode: 0644]
extlib/mimalloc/docs/group__aligned.js [new file with mode: 0644]
extlib/mimalloc/docs/group__analysis.html [new file with mode: 0644]
extlib/mimalloc/docs/group__analysis.js [new file with mode: 0644]
extlib/mimalloc/docs/group__analysis_structmi__heap__area__t.js [new file with mode: 0644]
extlib/mimalloc/docs/group__cpp.html [new file with mode: 0644]
extlib/mimalloc/docs/group__cpp.js [new file with mode: 0644]
extlib/mimalloc/docs/group__extended.html [new file with mode: 0644]
extlib/mimalloc/docs/group__extended.js [new file with mode: 0644]
extlib/mimalloc/docs/group__heap.html [new file with mode: 0644]
extlib/mimalloc/docs/group__heap.js [new file with mode: 0644]
extlib/mimalloc/docs/group__malloc.html [new file with mode: 0644]
extlib/mimalloc/docs/group__malloc.js [new file with mode: 0644]
extlib/mimalloc/docs/group__options.html [new file with mode: 0644]
extlib/mimalloc/docs/group__options.js [new file with mode: 0644]
extlib/mimalloc/docs/group__posix.html [new file with mode: 0644]
extlib/mimalloc/docs/group__posix.js [new file with mode: 0644]
extlib/mimalloc/docs/group__typed.html [new file with mode: 0644]
extlib/mimalloc/docs/group__typed.js [new file with mode: 0644]
extlib/mimalloc/docs/group__zeroinit.html [new file with mode: 0644]
extlib/mimalloc/docs/group__zeroinit.js [new file with mode: 0644]
extlib/mimalloc/docs/index.html [new file with mode: 0644]
extlib/mimalloc/docs/jquery.js [new file with mode: 0644]
extlib/mimalloc/docs/mimalloc-doc_8h_source.html [new file with mode: 0644]
extlib/mimalloc/docs/mimalloc-doxygen.css [new file with mode: 0644]
extlib/mimalloc/docs/mimalloc-logo.svg [new file with mode: 0644]
extlib/mimalloc/docs/modules.html [new file with mode: 0644]
extlib/mimalloc/docs/modules.js [new file with mode: 0644]
extlib/mimalloc/docs/nav_f.png [new file with mode: 0644]
extlib/mimalloc/docs/nav_g.png [new file with mode: 0644]
extlib/mimalloc/docs/nav_h.png [new file with mode: 0644]
extlib/mimalloc/docs/navtree.css [new file with mode: 0644]
extlib/mimalloc/docs/navtree.js [new file with mode: 0644]
extlib/mimalloc/docs/navtreedata.js [new file with mode: 0644]
extlib/mimalloc/docs/navtreeindex0.js [new file with mode: 0644]
extlib/mimalloc/docs/open.png [new file with mode: 0644]
extlib/mimalloc/docs/overrides.html [new file with mode: 0644]
extlib/mimalloc/docs/pages.html [new file with mode: 0644]
extlib/mimalloc/docs/resize.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_2.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_2.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_3.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_3.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_4.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_4.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_5.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_5.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_6.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_6.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_7.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_7.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_8.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_8.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_9.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_9.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_a.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_a.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_b.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_b.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_c.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_c.js [new file with mode: 0644]
extlib/mimalloc/docs/search/all_d.html [new file with mode: 0644]
extlib/mimalloc/docs/search/all_d.js [new file with mode: 0644]
extlib/mimalloc/docs/search/classes_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/classes_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/close.png [new file with mode: 0644]
extlib/mimalloc/docs/search/enums_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/enums_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/enumvalues_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/enumvalues_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/enumvalues_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/enumvalues_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/functions_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/functions_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/functions_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/functions_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_2.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_2.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_3.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_3.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_4.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_4.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_5.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_5.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_6.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_6.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_7.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_7.js [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_8.html [new file with mode: 0644]
extlib/mimalloc/docs/search/groups_8.js [new file with mode: 0644]
extlib/mimalloc/docs/search/mag_sel.png [new file with mode: 0644]
extlib/mimalloc/docs/search/nomatches.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_2.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_2.js [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_3.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_3.js [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_4.html [new file with mode: 0644]
extlib/mimalloc/docs/search/pages_4.js [new file with mode: 0644]
extlib/mimalloc/docs/search/search.css [new file with mode: 0644]
extlib/mimalloc/docs/search/search.js [new file with mode: 0644]
extlib/mimalloc/docs/search/search_l.png [new file with mode: 0644]
extlib/mimalloc/docs/search/search_m.png [new file with mode: 0644]
extlib/mimalloc/docs/search/search_r.png [new file with mode: 0644]
extlib/mimalloc/docs/search/searchdata.js [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_2.html [new file with mode: 0644]
extlib/mimalloc/docs/search/typedefs_2.js [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_0.html [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_0.js [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_1.html [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_1.js [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_2.html [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_2.js [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_3.html [new file with mode: 0644]
extlib/mimalloc/docs/search/variables_3.js [new file with mode: 0644]
extlib/mimalloc/docs/splitbar.png [new file with mode: 0644]
extlib/mimalloc/docs/sync_off.png [new file with mode: 0644]
extlib/mimalloc/docs/sync_on.png [new file with mode: 0644]
extlib/mimalloc/docs/tab_a.png [new file with mode: 0644]
extlib/mimalloc/docs/tab_b.png [new file with mode: 0644]
extlib/mimalloc/docs/tab_h.png [new file with mode: 0644]
extlib/mimalloc/docs/tab_s.png [new file with mode: 0644]
extlib/mimalloc/docs/tabs.css [new file with mode: 0644]
extlib/mimalloc/docs/using.html [new file with mode: 0644]
extlib/mimalloc/ide/vs2017/mimalloc-override.vcxproj
extlib/mimalloc/ide/vs2017/mimalloc-override.vcxproj.filters
extlib/mimalloc/ide/vs2017/mimalloc.vcxproj
extlib/mimalloc/ide/vs2017/mimalloc.vcxproj.filters
extlib/mimalloc/ide/vs2019/mimalloc-override.vcxproj
extlib/mimalloc/ide/vs2019/mimalloc-override.vcxproj.filters
extlib/mimalloc/ide/vs2019/mimalloc-test-stress.vcxproj
extlib/mimalloc/ide/vs2019/mimalloc.vcxproj
extlib/mimalloc/ide/vs2019/mimalloc.vcxproj.filters
extlib/mimalloc/include/mimalloc-atomic.h
extlib/mimalloc/include/mimalloc-internal.h
extlib/mimalloc/include/mimalloc-new-delete.h
extlib/mimalloc/include/mimalloc-override.h
extlib/mimalloc/include/mimalloc-types.h
extlib/mimalloc/include/mimalloc.h
extlib/mimalloc/readme.md
extlib/mimalloc/src/alloc-aligned.c
extlib/mimalloc/src/alloc-override-osx.c
extlib/mimalloc/src/alloc-override.c
extlib/mimalloc/src/alloc-posix.c
extlib/mimalloc/src/alloc.c
extlib/mimalloc/src/arena.c
extlib/mimalloc/src/bitmap.c [new file with mode: 0644]
extlib/mimalloc/src/bitmap.h [new file with mode: 0644]
extlib/mimalloc/src/bitmap.inc.c [deleted file]
extlib/mimalloc/src/heap.c
extlib/mimalloc/src/init.c
extlib/mimalloc/src/options.c
extlib/mimalloc/src/os.c
extlib/mimalloc/src/page-queue.c
extlib/mimalloc/src/page.c
extlib/mimalloc/src/random.c
extlib/mimalloc/src/region.c
extlib/mimalloc/src/segment-cache.c [new file with mode: 0644]
extlib/mimalloc/src/segment.c
extlib/mimalloc/src/static.c
extlib/mimalloc/src/stats.c
extlib/mimalloc/test/CMakeLists.txt
extlib/mimalloc/test/main-override-static.c
extlib/mimalloc/test/main-override.c
extlib/mimalloc/test/main-override.cpp
extlib/mimalloc/test/test-api-fill.c [new file with mode: 0644]
extlib/mimalloc/test/test-api.c
extlib/mimalloc/test/test-stress.c
extlib/mimalloc/test/testhelper.h [new file with mode: 0644]
include/slvs.h
pkg/flatpak/.gitignore [deleted file]
pkg/flatpak/com.solvespace.SolveSpace.json
pkg/snap/.gitignore [deleted file]
pkg/snap/snap/snapcraft.yaml
res/CMakeLists.txt
res/fonts/unicode.lff.gz
res/fonts/unifont.hex.gz [new file with mode: 0644]
res/freedesktop/com.solvespace.SolveSpace.metainfo.xml.in [new file with mode: 0644]
res/freedesktop/solvespace-16x16.xpm [deleted file]
res/freedesktop/solvespace-24x24.xpm [deleted file]
res/freedesktop/solvespace-32x32.xpm [deleted file]
res/freedesktop/solvespace-48x48.xpm [deleted file]
res/freedesktop/solvespace-flatpak.desktop.in
res/freedesktop/solvespace-snap.desktop
res/freedesktop/solvespace.desktop.in
res/icons/graphics-window/angle.png
res/icons/graphics-window/arc.png
res/icons/graphics-window/assemble.png
res/icons/graphics-window/bezier.png
res/icons/graphics-window/circle.png
res/icons/graphics-window/construction.png
res/icons/graphics-window/equal.png
res/icons/graphics-window/extrude.png
res/icons/graphics-window/helix.png
res/icons/graphics-window/horiz.png
res/icons/graphics-window/image.png
res/icons/graphics-window/in3d.png
res/icons/graphics-window/lathe.png
res/icons/graphics-window/length.png
res/icons/graphics-window/line.png
res/icons/graphics-window/ontoworkplane.png
res/icons/graphics-window/other-supp.png
res/icons/graphics-window/parallel.png
res/icons/graphics-window/perpendicular.png
res/icons/graphics-window/point.png
res/icons/graphics-window/pointonx.png
res/icons/graphics-window/rectangle.png
res/icons/graphics-window/ref.png
res/icons/graphics-window/revolve.png
res/icons/graphics-window/same-orientation.png
res/icons/graphics-window/sketch-in-3d.png
res/icons/graphics-window/sketch-in-plane.png
res/icons/graphics-window/step-rotate.png
res/icons/graphics-window/step-translate.png
res/icons/graphics-window/symmetric.png
res/icons/graphics-window/tangent-arc.png
res/icons/graphics-window/text.png
res/icons/graphics-window/trim.png
res/icons/graphics-window/vert.png
res/icons/text-window/constraint.png
res/icons/text-window/construction.png
res/icons/text-window/edges.png
res/icons/text-window/faces.png
res/icons/text-window/mesh.png
res/icons/text-window/normal.png
res/icons/text-window/occluded-invisible.png
res/icons/text-window/occluded-stippled.png
res/icons/text-window/occluded-visible.png
res/icons/text-window/outlines.png
res/icons/text-window/point.png
res/icons/text-window/workplane.png
res/locales.txt
res/locales/de_DE.po
res/locales/en_US.po
res/locales/es_AR.po [new file with mode: 0644]
res/locales/fr_FR.po
res/locales/ru_RU.po
res/locales/tr_TR.po [new file with mode: 0644]
res/locales/uk_UA.po
res/locales/zh_CN.po
res/messages.pot
res/threejs/SolveSpaceControls.js
res/threejs/three-r111.min.js.gz [new file with mode: 0644]
res/win32/versioninfo.rc.in
src/CMakeLists.txt
src/clipboard.cpp
src/config.h.in
src/confscreen.cpp
src/constraint.cpp
src/constrainteq.cpp
src/describescreen.cpp
src/draw.cpp
src/drawconstraint.cpp
src/drawentity.cpp
src/dsc.h
src/export.cpp
src/exportstep.cpp
src/exportvector.cpp
src/expr.cpp
src/expr.h
src/file.cpp
src/generate.cpp
src/graphicswin.cpp
src/group.cpp
src/groupmesh.cpp
src/importidf.cpp
src/importmesh.cpp [new file with mode: 0644]
src/lib.cpp
src/modify.cpp
src/mouse.cpp
src/platform/entrycli.cpp
src/platform/gui.cpp
src/platform/gui.h
src/platform/guigtk.cpp
src/platform/guimac.mm
src/platform/guiwin.cpp
src/platform/platform.h
src/render/render2d.cpp
src/resource.cpp
src/resource.h
src/sketch.h
src/solvespace.cpp
src/solvespace.h
src/srf/boolean.cpp
src/srf/curve.cpp
src/srf/merge.cpp
src/srf/raycast.cpp
src/srf/shell.cpp [new file with mode: 0644]
src/srf/surface.cpp
src/srf/surfinter.cpp
src/srf/triangulate.cpp
src/style.cpp
src/system.cpp
src/textscreens.cpp
src/textwin.cpp
src/toolbar.cpp
src/ttf.cpp
src/ui.h
src/view.cpp
test/constraint/equal_angle/normal.png
test/constraint/equal_angle/normal.slvs
test/constraint/equal_angle/normal_old_version.slvs [new file with mode: 0644]
test/constraint/equal_angle/test.cpp
test/request/image/linked.png [new file with mode: 0644]
test/request/image/normal.png [new file with mode: 0644]
test/request/image/test.cpp

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644 (file)
index 0000000..e9d7df9
--- /dev/null
@@ -0,0 +1,17 @@
+### System information
+
+- **SolveSpace version:** <!--e.g. 3.0~3dd2fc00; go to Help → About...-->
+- **Operating system:** <!--e.g. Debian testing-->
+
+### Expected behavior
+
+<!--What should have happened?-->
+
+### Actual behavior
+
+<!--What actually happened?-->
+
+### Additional information
+
+<!--For bugs, please attach a savefile that shows the problematic behavior.
+You can attach `.slvs` files by archiving them into a `.zip` first.-->
diff --git a/.github/scripts/build-macos.sh b/.github/scripts/build-macos.sh
new file mode 100755 (executable)
index 0000000..3394a8a
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh -xe
+
+ENABLE_SANITIZERS="OFF"
+if [ "$1" = "release" ]; then
+    BUILD_TYPE="RelWithDebInfo"
+    ENABLE_LTO="ON"
+else
+    BUILD_TYPE="Debug"
+    ENABLE_LTO="OFF"
+fi
+
+# this is an option for our Github CI only, since it doesn't have a macos arm64 image yet
+CMAKE_GENERATOR="Unix Makefiles"
+CMAKE_PREFIX_PATH=""
+if [ "$2" = "arm64" ]; then
+    OSX_ARCHITECTURE="arm64"
+    CMAKE_PREFIX_PATH=$(find /tmp/libomp-arm64/libomp -depth 1)
+    git apply cmake/libpng-macos-arm64.patch || echo "Could not apply patch, probably already patched..."
+    mkdir build-arm64 || true
+    cd build-arm64
+elif [ "$2" = "x86_64" ]; then
+    OSX_ARCHITECTURE="x86_64"
+    CMAKE_PREFIX_PATH=$(find /tmp/libomp-x86_64/libomp -depth 1)
+    mkdir build || true
+    cd build
+else
+    mkdir build || true
+    cd build
+fi
+
+if [ "$3" = "xcode" ]; then
+    CMAKE_GENERATOR="Xcode"
+fi
+
+cmake \
+    -G "${CMAKE_GENERATOR}" \
+    -D CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
+    -D CMAKE_OSX_ARCHITECTURES="${OSX_ARCHITECTURE}" \
+    -D CMAKE_BUILD_TYPE="${BUILD_TYPE}" \
+    -D ENABLE_OPENMP="ON" \
+    -D ENABLE_SANITIZERS="${ENABLE_SANITIZERS}" \
+    -D ENABLE_LTO="${ENABLE_LTO}" \
+    ..
+
+if [ "$3" = "xcode" ]; then
+    open solvespace.xcodeproj
+else
+    cmake --build . --config "${BUILD_TYPE}" -j$(sysctl -n hw.logicalcpu)
+    if [ $(uname -m) = "$2" ]; then
+        make -j$(sysctl -n hw.logicalcpu) test_solvespace
+    fi
+fi
\ No newline at end of file
diff --git a/.github/scripts/build-snap.sh b/.github/scripts/build-snap.sh
new file mode 100755 (executable)
index 0000000..665e561
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -xe
+
+./pkg/snap/build.sh --use-lxd
diff --git a/.github/scripts/build-ubuntu.sh b/.github/scripts/build-ubuntu.sh
new file mode 100755 (executable)
index 0000000..4c8f4ea
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -xe
+
+mkdir build
+cd build
+cmake \
+  -DCMAKE_BUILD_TYPE="Debug" \
+  -DENABLE_OPENMP="ON" \
+  -DENABLE_SANITIZERS="ON" \
+  ..
+make -j$(nproc) VERBOSE=1
+make test_solvespace
diff --git a/.github/scripts/build-windows.sh b/.github/scripts/build-windows.sh
new file mode 100755 (executable)
index 0000000..e81fb2a
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh -xe
+
+mkdir build
+cd build
+
+if [ "$1" = "release" ]; then
+    if [ "$2" = "openmp" ]; then
+        ENABLE_OPENMP="ON"
+    else
+        ENABLE_OPENMP="OFF"
+    fi
+    BUILD_TYPE=RelWithDebInfo
+    cmake \
+        -G "Visual Studio 16 2019" \
+        -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
+        -DENABLE_OPENMP="${ENABLE_OPENMP}" \
+        -DENABLE_LTO=ON \
+        -DCMAKE_GENERATOR_PLATFORM="Win32" \
+        ..
+else
+    BUILD_TYPE=Debug
+    cmake \
+        -G "Visual Studio 16 2019" \
+        -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
+        -DENABLE_OPENMP="ON" \
+        -DCMAKE_GENERATOR_PLATFORM="Win32" \
+        ..
+fi
+
+cmake --build . --config "${BUILD_TYPE}" -- -maxcpucount
+
+bin/$BUILD_TYPE/solvespace-testsuite.exe
+
+if [ "$2" = "openmp" ]; then
+    mv bin/$BUILD_TYPE/solvespace.exe bin/$BUILD_TYPE/solvespace-openmp.exe
+fi
diff --git a/.github/scripts/install-macos.sh b/.github/scripts/install-macos.sh
new file mode 100755 (executable)
index 0000000..bb39bcd
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh -xe
+
+if [ "$1" = "ci" ]; then
+    armloc=$(brew fetch --bottle-tag=arm64_big_sur libomp | grep -i downloaded | grep tar.gz | cut -f2 -d:)
+    x64loc=$(brew fetch --bottle-tag=big_sur libomp | grep -i downloaded | grep tar.gz | cut -f2 -d:)
+    cp $armloc /tmp/libomp-arm64.tar.gz
+    mkdir /tmp/libomp-arm64 || true
+    tar -xzvf /tmp/libomp-arm64.tar.gz -C /tmp/libomp-arm64
+    cp $x64loc /tmp/libomp-x86_64.tar.gz
+    mkdir /tmp/libomp-x86_64 || true
+    tar -xzvf /tmp/libomp-x86_64.tar.gz -C /tmp/libomp-x86_64
+else
+    brew install libomp
+fi
+
+git submodule update --init extlib/cairo extlib/freetype extlib/libdxfrw extlib/libpng extlib/mimalloc extlib/pixman extlib/zlib extlib/eigen
diff --git a/.github/scripts/install-snap.sh b/.github/scripts/install-snap.sh
new file mode 100755 (executable)
index 0000000..e10a91d
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh -xe
+
+sudo /snap/bin/lxd waitready
+sudo /snap/bin/lxd init --auto
+sudo chgrp travis /var/snap/lxd/common/lxd/unix.socket
+mkdir -p "$TRAVIS_BUILD_DIR/snaps-cache"
diff --git a/.github/scripts/install-ubuntu.sh b/.github/scripts/install-ubuntu.sh
new file mode 100755 (executable)
index 0000000..6033f73
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh -xe
+
+sudo apt-get update -qq
+
+sudo apt-get install -q -y \
+  zlib1g-dev libpng-dev libcairo2-dev libfreetype6-dev libjson-c-dev \
+  libfontconfig1-dev libgtkmm-3.0-dev libpangomm-1.4-dev libgl-dev \
+  libgl-dev libglu-dev libspnav-dev
+
+git submodule update --init extlib/libdxfrw extlib/mimalloc extlib/eigen
diff --git a/.github/scripts/install-windows.sh b/.github/scripts/install-windows.sh
new file mode 100755 (executable)
index 0000000..738d67d
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -xe
+
+git submodule update --init
diff --git a/.github/scripts/sign-macos.sh b/.github/scripts/sign-macos.sh
new file mode 100755 (executable)
index 0000000..8e944d3
--- /dev/null
@@ -0,0 +1,91 @@
+#!/bin/bash -xe
+
+lipo \
+    -create \
+        build/bin/SolveSpace.app/Contents/Resources/libomp.dylib \
+        build-arm64/bin/SolveSpace.app/Contents/Resources/libomp.dylib \
+    -output \
+        build/bin/SolveSpace.app/Contents/Resources/libomp.dylib
+
+lipo \
+    -create \
+        build/bin/SolveSpace.app/Contents/MacOS/SolveSpace \
+        build-arm64/bin/SolveSpace.app/Contents/MacOS/SolveSpace \
+    -output \
+        build/bin/SolveSpace.app/Contents/MacOS/SolveSpace
+
+lipo \
+    -create \
+        build/bin/SolveSpace.app/Contents/MacOS/solvespace-cli \
+        build-arm64/bin/SolveSpace.app/Contents/MacOS/solvespace-cli \
+    -output \
+        build/bin/SolveSpace.app/Contents/MacOS/solvespace-cli
+
+cd build
+
+openmp="bin/SolveSpace.app/Contents/Resources/libomp.dylib"
+app="bin/SolveSpace.app"
+dmg="bin/SolveSpace.dmg"
+bundle_id="com.solvespace.solvespace"
+
+if [ "$CI" = "true" ]; then
+    # get the signing certificate (this is the Developer ID:Application: Your Name, exported to a p12 file, then converted to base64, e.g.: cat ~/Desktop/certificate.p12 | base64 | pbcopy)
+    echo $MACOS_CERTIFICATE_P12 | base64 --decode > certificate.p12
+
+    # create a keychain
+    security create-keychain -p secret build.keychain
+    security default-keychain -s build.keychain
+    security unlock-keychain -p secret build.keychain
+
+    # import the key
+    security import certificate.p12 -k build.keychain -P "${MACOS_CERTIFICATE_PASSWORD}" -T /usr/bin/codesign
+
+    security set-key-partition-list -S apple-tool:,apple: -s -k secret build.keychain
+
+    # check if all is good
+    security find-identity -v
+fi
+
+# sign openmp
+codesign -s "${MACOS_DEVELOPER_ID}" --timestamp --options runtime -f --deep "${openmp}"
+
+# sign the .app
+codesign -s "${MACOS_DEVELOPER_ID}" --timestamp --options runtime -f --deep "${app}"
+
+# create the .dmg from the signed .app
+hdiutil create -srcfolder "${app}" "${dmg}"
+
+# sign the .dmg
+codesign -s "${MACOS_DEVELOPER_ID}" --timestamp --options runtime -f --deep "${dmg}"
+
+# notarize and store request uuid in variable
+notarize_uuid=$(xcrun altool --notarize-app --primary-bundle-id "${bundle_id}" --username "${MACOS_APPSTORE_USERNAME}" --password "${MACOS_APPSTORE_APP_PASSWORD}" --file "${dmg}" 2>&1 | grep RequestUUID | awk '{print $3'})
+
+echo $notarize_uuid
+
+# wait a bit so we don't get errors during checking
+sleep 10
+
+success=0
+for (( ; ; ))
+do
+    echo "Checking progress..."
+    progress=$(xcrun altool --notarization-info "${notarize_uuid}" -u "${MACOS_APPSTORE_USERNAME}" -p "${MACOS_APPSTORE_APP_PASSWORD}" 2>&1)
+    # echo "${progress}"
+    if [ $? -ne 0 ] || [[  "${progress}" =~ "Invalid" ]] ; then
+        echo "Error with notarization. Exiting"
+        break
+    fi
+    if [[  "${progress}" =~ "success" ]]; then
+        success=1
+        break
+    else
+        echo "Not completed yet. Sleeping for 10 seconds"
+    fi
+    sleep 10
+done
+
+# staple
+xcrun stapler staple "${dmg}"
\ No newline at end of file
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
new file mode 100644 (file)
index 0000000..a14afc5
--- /dev/null
@@ -0,0 +1,190 @@
+name: CD
+
+on:
+  push:
+    branches:
+      - master
+  release:
+    types:
+      - created
+
+jobs:
+  cancel_previous_runs:
+    runs-on: ubuntu-latest
+    name: Cancel Previous Runs
+    steps:
+    - uses: styfle/cancel-workflow-action@0.8.0
+      with:
+        access_token: ${{ github.token }}
+
+  test_ubuntu:
+    needs: [cancel_previous_runs]
+    runs-on: ubuntu-18.04
+    name: Test Ubuntu
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-ubuntu.sh
+    - name: Build & Test
+      run: .github/scripts/build-ubuntu.sh
+
+  test_windows:
+    needs: [cancel_previous_runs]
+    runs-on: windows-2019
+    name: Test Windows
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-windows.sh
+      shell: bash
+    - name: Build & Test
+      run: .github/scripts/build-windows.sh
+      shell: bash
+
+  test_macos:
+    needs: [cancel_previous_runs]
+    runs-on: macos-10.15
+    name: Test macOS
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-macos.sh ci
+    - name: Build & Test
+      run: .github/scripts/build-macos.sh debug arm64 && .github/scripts/build-macos.sh debug x86_64
+
+  build_release_windows:
+    needs: [test_ubuntu, test_windows, test_macos]
+    name: Build Release Windows
+    runs-on: windows-2019
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Dependencies
+        run: .github/scripts/install-windows.sh
+        shell: bash
+      - name: Build & Test
+        run: .github/scripts/build-windows.sh release
+        shell: bash
+      - name: Upload artifact
+        uses: actions/upload-artifact@v2
+        with:
+          name: windows
+          path: build/bin/RelWithDebInfo/solvespace.exe
+  
+  build_release_windows_openmp:
+    needs: [test_ubuntu, test_windows, test_macos]
+    name: Build Release Windows (OpenMP)
+    runs-on: windows-2019
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Dependencies
+        run: .github/scripts/install-windows.sh
+        shell: bash
+      - name: Build & Test
+        run: .github/scripts/build-windows.sh release openmp
+        shell: bash
+      - name: Upload artifact
+        uses: actions/upload-artifact@v2
+        with:
+          name: windows-openmp
+          path: build/bin/RelWithDebInfo/solvespace-openmp.exe
+
+  build_release_macos:
+    needs: [test_ubuntu, test_windows, test_macos]
+    name: Build Release macOS
+    runs-on: macos-10.15
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-macos.sh ci
+    - name: Build & Test
+      run: .github/scripts/build-macos.sh release arm64 && .github/scripts/build-macos.sh release x86_64
+    - name: Sign Build
+      run: .github/scripts/sign-macos.sh
+      env:
+        MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
+        MACOS_CERTIFICATE_P12: ${{ secrets.MACOS_CERTIFICATE_P12 }}
+        MACOS_APPSTORE_APP_PASSWORD: ${{ secrets.MACOS_APPSTORE_APP_PASSWORD }}
+        MACOS_APPSTORE_USERNAME: ${{ secrets.MACOS_APPSTORE_USERNAME }}
+        MACOS_DEVELOPER_ID: ${{ secrets.MACOS_DEVELOPER_ID }}
+    - name: Upload artifact
+      uses: actions/upload-artifact@v2
+      with:
+        name: macos
+        path: build/bin/SolveSpace.dmg
+
+  deploy_snap_amd64:
+    needs: [test_ubuntu, test_windows, test_macos]
+    name: Deploy AMD64 Snap
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Fetch Tags
+      run: git fetch --force --tags
+    - name: Set Up Source
+      run: rsync --filter=":- .gitignore" -r ./ pkg/snap/solvespace-snap-src
+    - name: Build Snap
+      uses: snapcore/action-build@v1
+      id: build
+      with:
+        path: pkg/snap
+    - name: Upload & Release to Edge
+      if: github.event_name == 'push'
+      uses: snapcore/action-publish@v1
+      with:
+        store_login: ${{ secrets.SNAPSTORE_LOGIN }}
+        snap: ${{ steps.build.outputs.snap }}
+        release: edge
+    - name: Upload & Release to Beta + Edge
+      if: github.event_name == 'release'
+      uses: snapcore/action-publish@v1
+      with:
+        store_login: ${{ secrets.SNAPSTORE_LOGIN }}
+        snap: ${{ steps.build.outputs.snap }}
+        release: edge,beta
+
+  upload_release_assets:
+    name: Upload Release Assets
+    needs: [build_release_windows, build_release_windows_openmp, build_release_macos]
+    if: "!cancelled() && github.event_name == 'release'"
+    runs-on: ubuntu-latest
+    steps:
+    - name: Download All Workflow Artifacts
+      uses: actions/download-artifact@v2
+    - name: Get Release Upload URL
+      id: get_upload_url
+      env:
+        event: ${{ toJson(github.event) }}
+      run: |
+        upload_url=$(echo "$event" | jq -r ".release.upload_url")
+        echo "::set-output name=upload_url::$upload_url"
+        echo "Upload URL: $upload_url"
+    - name: Upload solvespace.exe
+      uses: actions/upload-release-asset@v1
+      continue-on-error: true
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
+        asset_path: windows/solvespace.exe
+        asset_name: solvespace.exe
+        asset_content_type: binary/octet-stream
+    - name: Upload solvespace-openmp.exe
+      uses: actions/upload-release-asset@v1
+      continue-on-error: true
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
+        asset_path: windows-openmp/solvespace-openmp.exe
+        asset_name: solvespace-openmp.exe
+        asset_content_type: binary/octet-stream
+    - name: Upload SolveSpace.dmg
+      uses: actions/upload-release-asset@v1
+      continue-on-error: true
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
+        asset_path: macos/SolveSpace.dmg
+        asset_name: SolveSpace.dmg
+        asset_content_type: binary/octet-stream
diff --git a/.github/workflows/source-tarball.yml b/.github/workflows/source-tarball.yml
new file mode 100644 (file)
index 0000000..8bc0622
--- /dev/null
@@ -0,0 +1,51 @@
+name: Source Tarball
+
+on:
+  release:
+    types:
+      - created
+
+jobs:
+  create_tarball:
+    name: Create & Upload Tarball
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+      with:
+        submodules: true
+        fetch-depth: 0
+    - name: Pack Tarball
+      id: pack_tarball
+      run: |
+        version="${GITHUB_REF#refs/tags/v}"
+        dir_name="solvespace-${version}"
+        archive_name="${dir_name}.tar.xz"
+        archive_path="${HOME}/${archive_name}"
+        
+        echo "::set-output name=archive_name::${archive_name}"
+        echo "::set-output name=archive_path::${archive_path}"
+
+        cd ..
+        tar \
+          --exclude-vcs \
+          --transform "s:^solvespace:${dir_name}:" \
+          -cvaf \
+          ${archive_path} \
+          solvespace
+    - name: Get Release Upload URL
+      id: get_upload_url
+      env:
+        event: ${{ toJson(github.event) }}
+      run: |
+        upload_url=$(echo "$event" | jq -r ".release.upload_url")
+        echo "::set-output name=upload_url::$upload_url"
+        echo "Upload URL: $upload_url"
+    - name: Upload Tarball
+      uses: actions/upload-release-asset@v1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.get_upload_url.outputs.upload_url }}
+        asset_path: ${{ steps.pack_tarball.outputs.archive_path }}
+        asset_name: ${{ steps.pack_tarball.outputs.archive_name }}
+        asset_content_type: binary/octet-stream
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644 (file)
index 0000000..1ca64b3
--- /dev/null
@@ -0,0 +1,44 @@
+name: Test
+
+on:
+  pull_request:
+    branches:
+      - master
+  push:
+    branches-ignore:
+      - master
+    tags-ignore:
+      - v*
+
+jobs:
+  test_ubuntu:
+      runs-on: ubuntu-18.04
+      name: Test Ubuntu
+      steps:
+      - uses: actions/checkout@v2
+      - name: Install Dependencies
+        run: .github/scripts/install-ubuntu.sh
+      - name: Build & Test
+        run: .github/scripts/build-ubuntu.sh
+
+  test_windows:
+    runs-on: windows-2019
+    name: Test Windows
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-windows.sh
+      shell: bash
+    - name: Build & Test
+      run: .github/scripts/build-windows.sh
+      shell: bash
+
+  test_macos:
+    runs-on: macos-10.15
+    name: Test macOS
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install Dependencies
+      run: .github/scripts/install-macos.sh ci
+    - name: Build & Test
+      run: .github/scripts/build-macos.sh debug arm64 && .github/scripts/build-macos.sh debug x86_64
index 8447d0ef4b422b53be9975bf9a73ddcc2f7a4887..7f6a4af0a345ba4d687a089183b2016eae112ddc 100644 (file)
 Changelog
 =========
 
+3.x  - since the 3.0 release, only available in edge builds
+---
+
+Constraints:
+
+* Arcs length ratio and difference.
+* Arc & Line length ratio and difference.
+* Allow comments to be associated with point entities.
+
+Sketching:
+
+* Support for pan, zoom and rotate trackpad gestures on macOS
+* Add "exploded view" to sketches via "\\" key. Shows sketch elements separated
+  by a configurable distance perpendicular to the sketch plane.
+* Added Feet-Inches as a unit of measure. Inputs are still in inches.
+  But the display shows feet, inches, and fraction of an inch.
+* Added an optional "pitch" parameter to helix extrusions (in the text window)
+* Allow use of Point & Normal to define "sketch-in-new-workplane".
+* Update "Property Browser" live while dragging the sketch.
+
+MISC:
+
+* Add a link to the GitHub commit from which SolveSpace was built in the Help
+  menu.
+* Make all points, vectors and normals shown in the Property Browser into
+  active links. This makes them explorable and selectable.
+* Load 16bit PNG images correctly by re-scaling to 8bit.
+* Fixed hang when trying to display characters missing from the embedded font.
+* The main window vertical size can be as small as the toolbar.
+* Configurable "SafeHeight" parameter instead of the fixed 5mm for G-code export.
+* Add Spanish / Argentina translation.
+* Move "perspective factor", "lighting direction" and "explode distance" from
+  the "configuration" screen to the "view" screen.
+* Add a "∆" suffix to groups which have "force to triangle mesh" ticked
+* Gray the group name in the text window for groups with suppressed solid model.
+* Added the ability to Link STL files.
+* When linking circuit boards (IDF .emn files) show keepout regions as construction entities.
+
+Performance:
+
+* Speed up sketches with many constraints by roughly 8x by using the Eigen
+  library in the solver. The maximum unknowns increased from 1024 to 2048.
+* Add a "suppress dof calculation" setting to groups - increases performance for
+  complex sketches.
+* More changes to the ID list implementation.
+
 3.0
 ---
 
 New sketch features:
-  * New intersection boolean operation for solid models.
-  * New groups, revolution and helical extrusion.
-  * Extrude, lathe, translate and rotate groups can use the "assembly"
-    boolean operation, to increase performance.
-  * The solid model of extrude and lathe groups can be suppressed,
-    for splitting a single model in multiple parts to export,
-    or if only the generated entities are desired, without the mesh.
-  * Translate and rotate groups can create n-dimensional arrays using
-    the "difference" and "assembly" boolean operations.
-  * A new sketch in workplane group can be created based on existing workplane.
-  * TTF text request has two additional points on the right side, which allow
-    constraining the width of text.
-  * Image requests can now be created, similar to TTF text requests.
-    This replaces the "style → background image" feature.
-  * Irrelevant points (e.g. arc center point) are not counted when estimating
-    the bounding box used to compute chord tolerance.
-  * When adding a constraint which has a label and is redundant with another
-    constraint, the constraint is added as a reference, avoiding an error.
-  * Datum points can be copied and pasted.
-  * "Split Curves at Intersection" can now split curves at point lying on curve,
-    not just at intersection of two curves.
-  * Property browser now shows amount of degrees of freedom in group list.
-    It also shows a yellow "err" if the sketch has problems (e.g. self
-    intersecting) that would propagate in subsequent groups.
+
+* New intersection boolean operation for solid models.
+* New groups, revolution and helical extrusion.
+* Extrude, lathe, translate and rotate groups can use the "assembly"
+  boolean operation, to increase performance.
+* The solid model of extrude and lathe groups can be suppressed,
+  for splitting a single model in multiple parts to export,
+  or if only the generated entities are desired, without the mesh.
+* Translate and rotate groups can create n-dimensional arrays using
+  the "difference" and "assembly" boolean operations.
+* A new sketch in workplane group can be created based on existing workplane.
+* TTF text request has two additional points on the right side, which allow
+  constraining the width of text.
+* Image requests can now be created, similar to TTF text requests.
+  This replaces the "style → background image" feature.
+* Irrelevant points (e.g. arc center point) are not counted when estimating
+  the bounding box used to compute chord tolerance.
+* When adding a constraint which has a label and is redundant with another
+  constraint, the constraint is added as a reference, avoiding an error.
+* Datum points can be copied and pasted.
+* "Split Curves at Intersection" can now split curves at point lying on curve,
+  not just at intersection of two curves.
+* Property browser now shows amount of degrees of freedom in group list.
+  It also shows a yellow "err" if the sketch has problems (e.g. self
+  intersecting) that would propagate in subsequent groups.
+* It is now possible to press "g" to toggle construction on new objects while
+  they are still being drawn.
+* Allow right click to end sketching of all entities.
 
 New constraint features:
-  * When dragging an arc or rectangle point, it will be automatically
-    constrained to other points with a click.
-  * When selecting a constraint, the requests it constraints can be selected
-    in the text window.
-  * When selecting an entity, the constraints applied to it can be selected
-    in the text window.
-  * Distance constraint labels can now be formatted to use SI prefixes.
-    Values are edited in the configured unit regardless of label format.
-  * When creating a constraint, if an exactly identical constraint already
-    exists, it is now selected instead of adding a redundant constraint.
-  * It is now possible to turn off automatic creation of horizontal/vertical
-    constraints on line segments.
-  * Automatic creation of constraints no longer happens if the constraint
-    would have been redundant with other ones.
-  * New option to open the constraint editor for newly created constraints
-    with a value.
+
+* When dragging an arc or rectangle point, it will be automatically
+  constrained to other points with a click.
+* When selecting a constraint, the requests it constraints can be selected
+  in the text window.
+* When selecting an entity, the constraints applied to it can be selected
+  in the text window.
+* Distance constraint labels can now be formatted to use SI prefixes.
+  Values are edited in the configured unit regardless of label format.
+* When creating a constraint, if an exactly identical constraint already
+  exists, it is now selected instead of adding a redundant constraint.
+* It is now possible to turn off automatic creation of horizontal/vertical
+  constraints on line segments.
+* Automatic creation of constraints no longer happens if the constraint
+  would have been redundant with other ones.
+* New option to open the constraint editor for newly created constraints
+  with a value.
+* New "redundant constraint timeout (in ms)" option to prevent UI freeze
+  when looking for redundant constraints.
+* Swap vertical and horizontal constraints when pasting rotated by 90/270
+  degrees.
 
 New export/import features:
-  * Link IDF circuit boards in an assembly (.emn files)
-  * Three.js: allow configuring projection for exported model, and initially
-    use the current viewport projection.
-  * Wavefront OBJ: a material file is exported alongside the model, containing
-    mesh color information.
-  * DXF/DWG: 3D DXF files are imported as construction entities, in 3d.
-  * [ADDED 2019-02-25](https://github.com/solvespace/solvespace/pull/384) and [REMOVED 2020-11-13](https://github.com/solvespace/solvespace/issues/795):
-    Q3D: [Q3D](https://github.com/q3k/q3d/) triangle meshes can now be
-    exported. This format allows to easily hack on triangle mesh data created
-    in SolveSpace, supports colour information and is more space efficient than
-    most other formats.
-  * VRML (WRL) triangle meshes can now be exported, useful for e.g. [KiCAD](http://kicad.org).
-  * Export 2d section: custom styled entities that lie in the same
-    plane as the exported section are included.
+
+* Link IDF circuit boards in an assembly (.emn files)
+* Three.js: allow configuring projection for exported model, and initially
+  use the current viewport projection.
+* Wavefront OBJ: a material file is exported alongside the model, containing
+  mesh color information.
+* DXF/DWG: 3D DXF files are imported as construction entities, in 3d.
+* VRML (WRL) triangle meshes can now be exported, useful for e.g. [KiCAD](http://kicad.org).
+* Export 2d section: custom styled entities that lie in the same
+  plane as the exported section are included.
+* Added ExportBackgroundColor in configuration for EPS, PDF, and SVG files.
+* STEP export includes object colors and transparency.
+* Default "line styles" have a new "export these objects" option.
 
 New rendering features:
-  * The "Show/hide hidden lines" button is now a tri-state button that allows
-    showing all lines (on top of shaded mesh), stippling occluded lines
-    or not drawing them at all.
-  * The "Show/hide outlines" button is now independent from "Show/hide edges".
+
+* The "Show/hide hidden lines" button is now a tri-state button that allows
+  showing all lines (on top of shaded mesh), stippling occluded lines
+  or not drawing them at all.
+* The "Show/hide outlines" button is now independent from "Show/hide edges".
+* "View | Darken Inactive Solids" added. When turned off and a "sketch in plane"
+  group is active solids form previous groups will not be "darkened" (have the
+  s000d-#def-dim-solid style applied to them).
 
 New measurement/analysis features:
-  * New choice for base unit, meters.
-  * New command for measuring total length of selected entities,
-    "Analyze → Measure Perimeter".
-  * New command for measuring center of mass, with live updates as the sketch
-    changes, "Analyze → Center of Mass".
-  * New option for displaying areas of closed contours.
-  * When calculating volume of the mesh, volume of the solid from the current
-    group is now shown alongside total volume of all solids.
-  * When calculating area, and faces are selected, calculate area of those faces
-    instead of the closed contour in the sketch.
-  * When selecting a point and a line, projected distance to current
-    workplane is displayed.
+
+* New choice for base unit, meters.
+* New command for measuring total length of selected entities,
+  "Analyze → Measure Perimeter".
+* New command for measuring center of mass, with live updates as the sketch
+  changes, "Analyze → Center of Mass".
+* New option for displaying areas of closed contours.
+* When calculating volume of the mesh, volume of the solid from the current
+  group is now shown alongside total volume of all solids.
+* When calculating area, and faces are selected, calculate area of those faces
+  instead of the closed contour in the sketch.
+* When selecting a point and a line, projected distance to current
+  workplane is displayed.
 
 Other new features:
-  * Added ExportBackgroundColor in configuration for EPS, PDF, and SVG files.
-  * Improvements to the text window for selected entities and constraints.
-  * Ambient light source added in text window to allow flat shaded renderings.
-  * New command-line interface, for batch exporting and more.
-  * The graphical interface now supports HiDPI screens on every OS.
-  * New option to lock Z axis to be always vertical, like in SketchUp.
-  * New button to hide all construction entities.
-  * New link to match the on-screen size of the sketch with its actual size,
-    "view → set to full scale".
-  * When zooming to fit, constraints are also considered.
-  * Ctrl-clicking entities now deselects them, as the inverse of clicking.
-  * When clicking on an entity that shares a place with other entities,
-    the entity from the current group is selected.
-  * When dragging an entity that shares a place with other entities,
-    the entity from a request is selected. For example, dragging a point on
-    a face of an extrusion coincident with the source sketch plane will
-    drag the point from the source sketch.
-  * The default font for TTF text is now Bitstream Vera Sans, which is
-    included in the resources such that it is available on any OS.
-  * In expressions, numbers can contain the digit group separator, "_".
-  * The "=" key is bound to "Zoom In", like "+" key.
-  * The numpad decimal separator key is bound to "." regardless of locale.
-  * On Windows, full-screen mode is implemented.
-  * On Linux, native file chooser dialog can be used.
-  * New edit menu items "Line Styles", "View Projection" and "Configuration"
-    that are shortcuts to the respective configuration screens.
-  * New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
-    to enable support for multi-threading and link-time optimization.
-  * "Shift+Scroll" for ten times finer zoom.
+
+* Improvements to the text window for selected entities and constraints.
+* Ambient light source added in text window to allow flat shaded renderings.
+* New command-line interface, for batch exporting and more.
+* The graphical interface now supports HiDPI screens on every OS.
+* New option to lock Z axis to be always vertical when rotating the view,
+  a.k.a. "turntable navigation".
+* New button to hide all construction entities.
+* New link to match the on-screen size of the sketch with its actual size,
+  "view → set to full scale".
+* When zooming to fit, constraints are also considered.
+* Ctrl-clicking entities now deselects them, as the inverse of clicking.
+* When clicking on an entity that shares a place with other entities,
+  the entity from the current group is selected.
+* When dragging an entity that shares a place with other entities,
+  the entity from a request is selected. For example, dragging a point on
+  a face of an extrusion coincident with the source sketch plane will
+  drag the point from the source sketch.
+* The default font for TTF text is now Bitstream Vera Sans, which is
+  included in the resources such that it is available on any OS.
+* In expressions, numbers can contain the digit group separator, "_".
+* The "=" key is bound to "Zoom In", like "+" key.
+* The numpad decimal separator key is bound to "." regardless of locale.
+* On Windows, full-screen mode is implemented.
+* On Linux, native file chooser dialog can be used.
+* New edit menu items "Line Styles", "View Projection" and "Configuration"
+  that are shortcuts to the respective configuration screens.
+* New cmake build options using -DENABLE_OPENMP=yes and -DENABLE_LTO=yes
+  to enable support for multi-threading and link-time optimization.
+* "Shift+Scroll" for ten times finer zoom.
+* Translations: Chinese, French, German, Russian, Turkish, Ukrainian.
 
 Bugs fixed:
-  * Fixed broken --view options for command line thumbnail image creation.
-  * Some errors in Triangulation of surfaces.
-  * Some NURNS boolean operations that failed particularly on surfaces
-    created with Lathe, Revolve, or Helix.
-  * Segfault in Remove Spline Point context menu.
-  * A point in 3d constrained to any line whose length is free no longer
-    causes the line length to collapse.
-  * Curve-line constraints (in 3d), parallel constraints (in 3d), and
-    same orientation constraints are more robust.
-  * Adding some constraints (vertical, midpoint, etc) twice errors out
-    immediately, instead of later and in a confusing way.
-  * Constraining a newly placed point to a hovered entity does not cause
-    spurious changes in the sketch.
-  * Points highlighted with "Analyze → Show Degrees of Freedom" are drawn
-    on top of all other geometry.
-  * A step rotate/translate group using a group forced to triangle mesh
-    as a source group also gets forced to triangle mesh.
-  * Paste Transformed with a negative scale does not invert arcs.
-  * The tangent arc now modifies the original entities instead of deleting
-    them, such that their constraints are retained.
-  * When linking a sketch file, missing custom styles are now imported from
-    the linked file.
-  * 3Dconnexion SpaceMouse should now work (on Windows and macOS X).
-  * Improved NURBS boolean operations on curved surfaces in some cases.
-  * Show only usable fonts in the font selector.
+
+* Fixed broken --view options for command line thumbnail image creation.
+* Some errors in Triangulation of surfaces.
+* Some NURNS boolean operations that failed particularly on surfaces
+  created with Lathe, Revolve, or Helix.
+* Segfault in Remove Spline Point context menu.
+* A point in 3d constrained to any line whose length is free no longer
+  causes the line length to collapse.
+* Curve-line constraints (in 3d), parallel constraints (in 3d), and
+  same orientation constraints are more robust.
+* Adding some constraints (vertical, midpoint, etc) twice errors out
+  immediately, instead of later and in a confusing way.
+* Constraining a newly placed point to a hovered entity does not cause
+  spurious changes in the sketch.
+* Points highlighted with "Analyze → Show Degrees of Freedom" are drawn
+  on top of all other geometry.
+* A step rotate/translate group using a group forced to triangle mesh
+  as a source group also gets forced to triangle mesh.
+* Paste Transformed with a negative scale does not invert arcs.
+* The tangent arc now modifies the original entities instead of deleting
+  them, such that their constraints are retained.
+* When linking a sketch file, missing custom styles are now imported from
+  the linked file.
+* 3Dconnexion SpaceMouse should now work (on Windows and macOS X).
+* Improved NURBS boolean operations on curved surfaces in some cases.
+* Show only usable fonts in the font selector.
 
 2.x
 ---
 
 Bug fixes:
-  * Do not crash when changing an unconstrained lathe group between
-    union and difference modes.
+
+* Do not crash when changing an unconstrained lathe group between
+  union and difference modes.
 
 2.3
 ---
 
 Bug fixes:
-  * Do not crash when applying a symmetry constraint to two points.
-  * Fix TTF font metrics again (properly this time).
-  * Fix the "draw back faces in red" option.
-  * Fix export of wireframe as 3D DXF.
-  * Various minor crashes.
+
+* Do not crash when applying a symmetry constraint to two points.
+* Fix TTF font metrics again (properly this time).
+* Fix the "draw back faces in red" option.
+* Fix export of wireframe as 3D DXF.
+* Various minor crashes.
 
 2.2
 ---
 
 Other new features:
-  * OS X: support 3Dconnexion devices (SpaceMouse, SpaceNavigator, etc).
-  * GTK: files with uppercase extensions can be opened.
+
+* OS X: support 3Dconnexion devices (SpaceMouse, SpaceNavigator, etc).
+* GTK: files with uppercase extensions can be opened.
 
 Bug fixes:
-  * Do not remove autosaves after successfully opening a file, preventing
-    data loss in case of two abnormal terminations in a row.
-  * Do not crash when changing autosave interval.
-  * Unbreak the "Show degrees of freedom" command.
-  * Three.js: correctly respond to controls when browser zoom is used.
-  * OS X: do not completely hide main window when defocused.
-  * GTK: unbreak 3Dconnexion support.
-  * When pasting transformed entities, multiply constraint values by scale.
-  * Fix TTF font metrics (restore the behavior from version 2.0).
-  * Forcibly show the current group once we start a drawing operation.
-  * DXF export: always declare layers before using them.
-  * Do not truncate operations on selections to first 32 selected entities.
-  * Translate and rotate groups inherit the "suppress solid model" setting.
-  * DXF: files with paths containing non-ASCII or spaces can be exported
-    or imported.
-  * Significantly improved performance when dragging an entity.
-  * Various crashes and minor glitches.
+
+* Do not remove autosaves after successfully opening a file, preventing
+  data loss in case of two abnormal terminations in a row.
+* Do not crash when changing autosave interval.
+* Unbreak the "Show degrees of freedom" command.
+* Three.js: correctly respond to controls when browser zoom is used.
+* OS X: do not completely hide main window when defocused.
+* GTK: unbreak 3Dconnexion support.
+* When pasting transformed entities, multiply constraint values by scale.
+* Fix TTF font metrics (restore the behavior from version 2.0).
+* Forcibly show the current group once we start a drawing operation.
+* DXF export: always declare layers before using them.
+* Do not truncate operations on selections to first 32 selected entities.
+* Translate and rotate groups inherit the "suppress solid model" setting.
+* DXF: files with paths containing non-ASCII or spaces can be exported
+  or imported.
+* Significantly improved performance when dragging an entity.
+* Various crashes and minor glitches.
 
 2.1
 ---
 
 New sketch features:
-  * Lathe groups create circle and face entities.
-  * New toolbar button for creating lathe groups.
-  * Chord tolerance is separated into two: display chord tolerance (specified
-    in percents, relative to model bounding box), and export chord tolerance
-    (specified in millimeters as absolute value).
-  * Bezier spline points can be added and removed after the spline is created.
-  * When an unconstrained extrusion is switched between "union" and
-    "difference", its normal is flipped.
-  * Groups can be added in the middle of the stack. Note that this results
-    in files incompatible with version 2.0.
-  * Active group can be removed.
-  * Removing an imported group does not cause all subsequent groups to also
-    be removed.
-  * When a new group with a solid is created, the color is taken from
-    a previous group with a solid, if any.
-  * Entities in a newly active group do not become visible.
-  * When entities are selected, "Zoom to fit" zooms to fit only these
-    entities and not the entire sketch.
-  * Zero-length edges are reported with a "zero-length error", not
-    "points not all coplanar".
+
+* Lathe groups create circle and face entities.
+* New toolbar button for creating lathe groups.
+* Chord tolerance is separated into two: display chord tolerance (specified
+  in percents, relative to model bounding box), and export chord tolerance
+  (specified in millimeters as absolute value).
+* Bezier spline points can be added and removed after the spline is created.
+* When an unconstrained extrusion is switched between "union" and
+  "difference", its normal is flipped.
+* Groups can be added in the middle of the stack. Note that this results
+  in files incompatible with version 2.0.
+* Active group can be removed.
+* Removing an imported group does not cause all subsequent groups to also
+  be removed.
+* When a new group with a solid is created, the color is taken from
+  a previous group with a solid, if any.
+* Entities in a newly active group do not become visible.
+* When entities are selected, "Zoom to fit" zooms to fit only these
+  entities and not the entire sketch.
+* Zero-length edges are reported with a "zero-length error", not
+  "points not all coplanar".
 
 New constraint features:
-  * Height of the font used for drawing constraint labels can be changed.
-  * New constraint, length difference, placed with J.
-    (Patch by Peter Ruevski)
-  * Horizontal/vertical constraints are automatically added if a line segment
-    is close enough to being horizontal/vertical. This can be disabled by
-    holding Ctrl.
-  * Reference dimensions and angles can be placed with Shift+D and Shift+N.
-  * Copying and pasting entities duplicates any constraints that only involve
-    entities in the clipboard, as well as selected comments.
-  * Diameter constraints can be shown as radius.
-  * The "pi" identifier can be used in expressions.
-  * Constraint labels can be snapped to grid.
-  * Integer angles are displayed without trailing zeroes.
-  * Angle constraints have proper reference lines and arrowheads.
-  * Extension lines are drawn for point-line distance constraints.
+
+* Height of the font used for drawing constraint labels can be changed.
+* New constraint, length difference, placed with J.
+  (Patch by Peter Ruevski)
+* Horizontal/vertical constraints are automatically added if a line segment
+  is close enough to being horizontal/vertical. This can be disabled by
+  holding Ctrl.
+* Reference dimensions and angles can be placed with Shift+D and Shift+N.
+* Copying and pasting entities duplicates any constraints that only involve
+  entities in the clipboard, as well as selected comments.
+* Diameter constraints can be shown as radius.
+* The "pi" identifier can be used in expressions.
+* Constraint labels can be snapped to grid.
+* Integer angles are displayed without trailing zeroes.
+* Angle constraints have proper reference lines and arrowheads.
+* Extension lines are drawn for point-line distance constraints.
 
 New solver features:
-  * Sketches with redundant and unsolvable constraints are distinguished.
-  * New group setting, "allow redundant constraints". Note that it makes
-    the solver less stable.
+
+* Sketches with redundant and unsolvable constraints are distinguished.
+* New group setting, "allow redundant constraints". Note that it makes
+  the solver less stable.
 
 New rendering and styling features:
-  * New line style parameter: stippling, based on ISO 128.
-  * Outlines of solids can be drawn in a particular style (by default, thick
-    lines) controlled by the "Show outline of solid model" button.
-  * Occluded edges can be drawn in a particular style (by default, stippled
-    with short dashes) controlled by the "Show hidden lines" button.
-  * Solids can be made transparent.
+
+* New line style parameter: stippling, based on ISO 128.
+* Outlines of solids can be drawn in a particular style (by default, thick
+  lines) controlled by the "Show outline of solid model" button.
+* Occluded edges can be drawn in a particular style (by default, stippled
+  with short dashes) controlled by the "Show hidden lines" button.
+* Solids can be made transparent.
 
 New export/import features:
-  * The old "import" command (for .slvs files) is renamed to "link".
-  * If a linked .slvs file is not found, first the relative path recorded
-    in the .slvs file is checked and then the absolute path; this is
-    an inversion of the previously used order. If it is still not found,
-    a dialog appears offering to locate it.
-  * DXF and DWG files can be imported, with point-coincident, horizontal and
-    vertical constraints automatically inferred from geometry, and distance
-    and angle constraints created when a dimension placed against geometry
-    exists.
-  * Triangle mesh can be exported for viewing in the browser through WebGL.
-  * Export dialogs remember the last file format used, and preselect it.
-  * Exported DXF files have exact circles, arcs and splines instead of
-    a piecewise linear approximation (unless hidden line removal was needed).
-  * Exported DXF files preserve color and line thickness.
-  * In exported DXF files, constraints are represented as DXF dimensions,
-    instead of piecewise linear geometry.
-  * When exporting 2d views, overlapping lines are removed.
+
+* The old "import" command (for .slvs files) is renamed to "link".
+* If a linked .slvs file is not found, first the relative path recorded
+  in the .slvs file is checked and then the absolute path; this is
+  an inversion of the previously used order. If it is still not found,
+  a dialog appears offering to locate it.
+* DXF and DWG files can be imported, with point-coincident, horizontal and
+  vertical constraints automatically inferred from geometry, and distance
+  and angle constraints created when a dimension placed against geometry
+  exists.
+* Triangle mesh can be exported for viewing in the browser through WebGL.
+* Export dialogs remember the last file format used, and preselect it.
+* Exported DXF files have exact circles, arcs and splines instead of
+  a piecewise linear approximation (unless hidden line removal was needed).
+* Exported DXF files preserve color and line thickness.
+* In exported DXF files, constraints are represented as DXF dimensions,
+  instead of piecewise linear geometry.
+* When exporting 2d views, overlapping lines are removed.
 
 Other new features:
-  * Native Linux (GTK 2 and GTK 3) and Mac OS X ports.
-  * Automatically save and then restore sketches if SolveSpace crashes.
-    (Patch by Marc Britten)
-  * Unicode is supported everywhere (filenames, group names, TTF text,
-    comments), although RTL scripts and scripts making heavy use of ligatures
-    are not rendered correctly.
-  * The vector font is grid-fitted when rendered on screen to make it easier
-    to read regardless of its size.
+
+* Native Linux (GTK 2 and GTK 3) and Mac OS X ports.
+* Automatically save and then restore sketches if SolveSpace crashes.
+  (Patch by Marc Britten)
+* Unicode is supported everywhere (filenames, group names, TTF text,
+  comments), although RTL scripts and scripts making heavy use of ligatures
+  are not rendered correctly.
+* The vector font is grid-fitted when rendered on screen to make it easier
+  to read regardless of its size.
 
 2.0
 ---
index 12948781f17c4a3a7eb185785e9c6590cd0e7fd5..7f08e95f2cd83ca4b6706c9a338c2bde27c57bba 100644 (file)
@@ -1,4 +1,5 @@
 # cmake configuration
+cmake_minimum_required(VERSION 3.9...3.19)
 
 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
     message(FATAL_ERROR
@@ -7,17 +8,9 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
             "    mkdir build && cd build && cmake ..")
 endif()
 
-cmake_minimum_required(VERSION 3.7.2 FATAL_ERROR)
-if(NOT CMAKE_VERSION VERSION_LESS 3.11.0)
-    cmake_policy(VERSION 3.11.0)
-endif()
-if(NOT CMAKE_VERSION VERSION_LESS 3.9)
-    # LTO/IPO with non-Intel compilers on Linux requires policy CMP0069 to be set to NEW.
-    # Set it explicitly until cmake_minimum_required is raised to >= 3.9.
-    cmake_policy(SET CMP0069 NEW)
-endif()
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+list(APPEND CMAKE_MODULE_PATH
     "${CMAKE_SOURCE_DIR}/cmake/")
+
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED YES)
 
@@ -27,10 +20,15 @@ set(CMAKE_USER_MAKE_RULES_OVERRIDE
 set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
    "${CMAKE_SOURCE_DIR}/cmake/cxx_flag_overrides.cmake")
 
-if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
 endif()
 
+if (APPLE)
+    # Docs say this must be set before the first project() call
+    set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "macOS minimum supported version")
+endif()
+
 # project
 
 # NOTE TO PACKAGERS: The embedded git commit hash is critical for rapid bug triage when the builds
@@ -40,10 +38,10 @@ include(GetGitCommitHash)
 # and instead uncomment the following, adding the complete git hash of the checkout you are using:
 # set(GIT_COMMIT_HASH 0000000000000000000000000000000000000000)
 
-project(solvespace)
-set(solvespace_VERSION_MAJOR 3)
-set(solvespace_VERSION_MINOR 0)
 string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH)
+project(solvespace
+    VERSION 3.1
+    LANGUAGES C CXX ASM)
 
 set(ENABLE_GUI        ON CACHE BOOL
     "Whether the graphical interface is enabled")
@@ -57,8 +55,11 @@ set(ENABLE_SANITIZERS OFF CACHE BOOL
     "Whether to enable Clang's AddressSanitizer and UndefinedBehaviorSanitizer")
 set(ENABLE_OPENMP     OFF CACHE BOOL
     "Whether geometric operations will be parallelized using OpenMP")
-set(ENABLE_LTO     OFF CACHE BOOL
+set(ENABLE_LTO        OFF CACHE BOOL
     "Whether interprocedural (global) optimizations are enabled")
+option(FORCE_VENDORED_Eigen3
+    "Whether we should use our bundled Eigen even in the presence of a system copy"
+    OFF)
 
 set(OPENGL 3 CACHE STRING "OpenGL version to use (one of: 1 3)")
 
@@ -68,10 +69,6 @@ if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
     set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_BINARY_DIR}/bin>)
 endif()
 
-if(NOT CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)
-    message(FATAL_ERROR "C and C++ compilers should be supplied by the same vendor")
-endif()
-
 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
     if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
         # GCC 4.8/4.9 ship with broken but present <regex>. meh.
@@ -82,11 +79,13 @@ endif()
 # common compiler flags
 include(CheckCXXCompilerFlag)
 
-set(FILE_PREFIX_MAP "-ffile-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.")
-check_cxx_compiler_flag("${FILE_PREFIX_MAP}" HAS_FILE_PREFIX_MAP)
-if(HAS_FILE_PREFIX_MAP)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FILE_PREFIX_MAP}")
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FILE_PREFIX_MAP}")
+if (NOT APPLE)
+    set(FILE_PREFIX_MAP "-ffile-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.")
+    check_cxx_compiler_flag("${FILE_PREFIX_MAP}" HAS_FILE_PREFIX_MAP)
+    if(HAS_FILE_PREFIX_MAP)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FILE_PREFIX_MAP}")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FILE_PREFIX_MAP}")
+    endif()
 endif()
 
 if(MINGW)
@@ -117,7 +116,12 @@ endif()
 if(ENABLE_OPENMP)
     find_package( OpenMP REQUIRED )
     if(OPENMP_FOUND)
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+        add_library(slvs_openmp INTERFACE)
+        target_compile_options(slvs_openmp INTERFACE ${OpenMP_CXX_FLAGS})
+        target_link_libraries(slvs_openmp INTERFACE
+            ${OpenMP_CXX_LIBRARIES})
+        target_include_directories(slvs_openmp INTERFACE SYSTEM
+            ${OpenMP_CXX_INCLUDE_DIRS})
         message(STATUS "found OpenMP, compiling with flags: " ${OpenMP_CXX_FLAGS} )
     endif()
 endif()
@@ -181,6 +185,9 @@ endif()
 message(STATUS "Using in-tree libdxfrw")
 add_subdirectory(extlib/libdxfrw)
 
+message(STATUS "Using in-tree eigen")
+include_directories(extlib/eigen)
+
 message(STATUS "Using in-tree mimalloc")
 set(MI_OVERRIDE OFF CACHE BOOL "")
 set(MI_BUILD_SHARED OFF CACHE BOOL "")
@@ -189,6 +196,18 @@ set(MI_BUILD_TESTS OFF CACHE BOOL "")
 add_subdirectory(extlib/mimalloc EXCLUDE_FROM_ALL)
 set(MIMALLOC_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/extlib/mimalloc/include)
 
+if(NOT FORCE_VENDORED_Eigen3)
+    find_package(Eigen3 CONFIG)
+endif()
+if(FORCE_VENDORED_Eigen3 OR NOT EIGEN3_FOUND)
+    message(STATUS "Using in-tree Eigen")
+    set(EIGEN3_FOUND             YES)
+    set(EIGEN3_INCLUDE_DIRS      ${CMAKE_SOURCE_DIR}/extlib/eigen)
+else()
+    message(STATUS "Using system Eigen: ${EIGEN3_INCLUDE_DIRS}")
+endif()
+
+
 if(WIN32 OR APPLE)
     # On Win32 and macOS we use vendored packages, since there is little to no benefit
     # to trying to find system versions. In particular, trying to link to libraries from
@@ -210,6 +229,12 @@ if(WIN32 OR APPLE)
     find_vendored_package(PNG libpng
         SKIP_INSTALL_ALL        ON
         PNG_LIBRARY             png_static
+        PNG_ARM_NEON            "off"
+        PNG_SHARED              OFF
+        PNG_STATIC              ON
+        PNG_EXECUTABLES         OFF
+        PNG_TESTS               OFF
+        PNG_FRAMEWORK           OFF
         PNG_PNG_INCLUDE_DIR     ${CMAKE_SOURCE_DIR}/extlib/libpng)
     list(APPEND PNG_PNG_INCLUDE_DIR ${CMAKE_BINARY_DIR}/extlib/libpng)
 
@@ -222,11 +247,14 @@ if(WIN32 OR APPLE)
         FREETYPE_INCLUDE_DIRS   ${CMAKE_SOURCE_DIR}/extlib/freetype/include)
 
     message(STATUS "Using in-tree pixman")
-    add_vendored_subdirectory(extlib/pixman)
     set(PIXMAN_FOUND            YES)
     set(PIXMAN_LIBRARY          pixman)
+    set(PIXMAN_BUILD_TESTS      OFF CACHE BOOL "")
+    set(PIXMAN_BUILD_DEMOS      OFF CACHE BOOL "")
+
     set(PIXMAN_INCLUDE_DIRS     ${CMAKE_SOURCE_DIR}/extlib/pixman/pixman)
     list(APPEND PIXMAN_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/extlib/pixman/pixman)
+    add_vendored_subdirectory(extlib/pixman)
 
     message(STATUS "Using in-tree cairo")
     add_vendored_subdirectory(extlib/cairo)
index aee8bb5924ccb003ceeb1217efbbbbae7974bbde..5636b39be4448a9add81a125936135970f1d22d5 100644 (file)
@@ -17,8 +17,8 @@ so any savefiles should first be archived.
 Licensing
 ---------------
 
-SolveSpace is licensed under the GPLv3 and any contributions must be made available
-under the terms of that license.
+SolveSpace is licensed under the GPLv3 or later and any contributions
+must be made available under the terms of that license.
 
 Contributing translations
 -------------------------
index 6e575a5d122ba990dbf81c9313b2b5e45f771477..55fe72deebaf31de869685557ee377cb87c043d3 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
+# SolveSpace
+
 <img src="res/freedesktop/solvespace-scalable.svg" width="70" height="70" alt="SolveSpace Logo" align="left">
 
-SolveSpace
-==========
 [![Build Status](https://github.com/solvespace/solvespace/workflows/CD/badge.svg)](https://github.com/solvespace/solvespace/actions)
 [![solvespace](https://snapcraft.io/solvespace/badge.svg)](https://snapcraft.io/solvespace)
 [![solvespace](https://snapcraft.io/solvespace/trending.svg?name=0)](https://snapcraft.io/solvespace)
@@ -9,159 +9,196 @@ SolveSpace
 This repository contains the source code of [SolveSpace][], a parametric
 2d/3d CAD.
 
-[solvespace]: http://solvespace.com
+[solvespace]: https://solvespace.com
 
-Community
----------
+## Community
 
 The official SolveSpace [website][sswebsite] has [tutorials][sstutorial],
 [reference manual][ssref] and a [forum][ssforum]; there is also an official
-IRC channel [#solvespace at irc.freenode.net][ssirc].
+IRC channel [#solvespace at web.libera.chat][ssirc].
 
 [sswebsite]: http://solvespace.com/
 [ssref]: http://solvespace.com/ref.pl
 [sstutorial]: http://solvespace.com/tutorial.pl
 [ssforum]: http://solvespace.com/forum.pl
-[ssirc]: https://webchat.freenode.net/?channels=solvespace
+[ssirc]: https://web.libera.chat/#solvespace
 
-Installation
-------------
+## Installation
 
-### Via official binary packages
+### Via Official Packages
 
-_Official_ release binary packages for macOS (>=10.6 64-bit) and Windows (>=Vista 32-bit) are
-available via [GitHub releases][rel]. These packages are automatically built by
-the SolveSpace maintainers for each stable release.
+_Official_ release packages for macOS (>=10.6 64-bit) and Windows
+(>=Vista 32-bit) are available via [GitHub releases][rel]. These packages are
+automatically built by the SolveSpace maintainers for each stable release.
 
 [rel]: https://github.com/solvespace/solvespace/releases
 
 ### Via Snap Store
 
-Builds from master are automatically released to the `edge` channel in the Snap Store. Those packages contain the latest improvements, but receive less testing than release builds.
+Official releases can be installed from the `stable` channel.
 
-Future official releases will appear in the `stable` channel.
+Builds from master are automatically released to the `edge` channel in the Snap
+Store. Those packages contain the latest improvements, but receive less testing
+than release builds.
 
 [![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/solvespace)
 
 Or install from a terminal:
 
+```sh
+# for the latest stable release:
+snap install solvespace
+
+# for the bleeding edge builds from master:
+snap install solvespace --edge
 ```
-snap install --edge solvespace
-```
 
-### Via third-party binary packages
+### Via automated edge builds
+
+> :warning: **Edge builds might be unstable or contain severe bugs!**
+> They are intended for experienced users to test new features or verify bugfixes.
 
-_Third-party_ nightly binary packages for Debian and Ubuntu are available
-via [notesalexp.org][notesalexp]. These packages are automatically built from non-released
-source code. The SolveSpace maintainers do not control the contents of these packages
-and cannot guarantee their functionality.
+Cutting edge builds from the latest master commit are available as zip archives
+from the following links:
 
-[notesalexp]: https://notesalexp.org/packages/en/source/solvespace/
+- [macOS](https://nightly.link/solvespace/solvespace/workflows/cd/master/macos.zip)
+- [Windows](https://nightly.link/solvespace/solvespace/workflows/cd/master/windows.zip)
+- [Windows with OpenMP enabled](https://nightly.link/solvespace/solvespace/workflows/cd/master/windows-openmp.zip)
+
+Extract the downloaded archive and install or execute the contained file as is
+appropriate for your platform.
 
 ### Via source code
 
 See below.
 
-Building on Linux
------------------
+## Building on Linux
 
 ### Building for Linux
 
-You will need the usual build tools, CMake, zlib, libpng, cairo, freetype.
-To build the GUI, you will need fontconfig, gtkmm 3.0 (version 3.16 or later), pangomm 1.4,
-OpenGL and OpenGL GLU, and optionally, the Space Navigator client library.
-On a Debian derivative (e.g. Ubuntu) these can be installed with:
+You will need the usual build tools, CMake, zlib, libpng, cairo, freetype. To
+build the GUI, you will need fontconfig, gtkmm 3.0 (version 3.16 or later),
+pangomm 1.4, OpenGL and OpenGL GLU, and optionally, the Space Navigator client
+library. On a Debian derivative (e.g. Ubuntu) these can be installed with:
 
-    sudo apt install git build-essential cmake zlib1g-dev libpng-dev \
-                     libcairo2-dev libfreetype6-dev libjson-c-dev \
-                     libfontconfig1-dev libgtkmm-3.0-dev libpangomm-1.4-dev \
-                     libgl-dev libglu-dev libspnav-dev
+```sh
+sudo apt install git build-essential cmake zlib1g-dev libpng-dev \
+            libcairo2-dev libfreetype6-dev libjson-c-dev \
+            libfontconfig1-dev libgtkmm-3.0-dev libpangomm-1.4-dev \
+            libgl-dev libglu-dev libspnav-dev
+```
 
-On a Redhat derivative (e.g. Fedora) the dependencies can be installed with:
+On a RedHat derivative (e.g. Fedora) the dependencies can be installed with:
 
-    sudo dnf install git gcc-c++ cmake zlib-devel libpng-devel \
-                     cairo-devel freetype-devel json-c-devel \
-                     fontconfig-devel gtkmm30-devel pangomm-devel \
-                     mesa-libGL-devel mesa-libGLU-devel libspnav-devel
+```sh
+sudo dnf install git gcc-c++ cmake zlib-devel libpng-devel \
+            cairo-devel freetype-devel json-c-devel \
+            fontconfig-devel gtkmm30-devel pangomm-devel \
+            mesa-libGL-devel mesa-libGLU-devel libspnav-devel
+```
 
 Before building, check out the project and the necessary submodules:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init extlib/libdxfrw extlib/mimalloc
+```sh
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init extlib/libdxfrw extlib/mimalloc extlib/eigen
+```
 
 After that, build SolveSpace as following:
 
-    mkdir build
-    cd build
-    cmake .. -DCMAKE_BUILD_TYPE=Release
-    make
-    sudo make install
+```sh
+mkdir build
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_OPENMP=ON
+make
 
-The graphical interface is built as `build/bin/solvespace`, and the command-line interface
-is built as `build/bin/solvespace-cli`. It is possible to build only the command-line interface
-by passing the `-DENABLE_GUI=OFF` flag to the cmake invocation.
+# Optionally
+sudo make install
+```
+
+Link Time Optimization is supported by adding `-DENABLE_LTO=ON` to cmake at the
+expense of longer build time.
+
+The graphical interface is built as `build/bin/solvespace`, and the command-line
+interface is built as `build/bin/solvespace-cli`. It is possible to build only
+the command-line interface by passing the `-DENABLE_GUI=OFF` flag to the cmake
+invocation.
 
 ### Building for Windows
 
-Ubuntu will require 20.04 or above. Cross-compiling with WSL is also confirmed to work.
+Ubuntu will require 20.04 or above. Cross-compiling with WSL is also confirmed
+to work.
 
-You will need the usual build tools, CMake, a Windows cross-compiler, and flatc. On a Debian derivative (e.g. Ubuntu) these can be installed with:
+You will need the usual build tools, CMake, and a Windows cross-compiler. On a
+Debian derivative (e.g. Ubuntu) these can be installed with:
 
-    apt-get install git build-essential cmake mingw-w64
+```sh
+apt-get install git build-essential cmake mingw-w64
+```
 
 Before building, check out the project and the necessary submodules:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init
+```sh
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init
+```
 
 Build 64-bit SolveSpace with the following:
 
-    mkdir build
-    cd build
-    cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw64.cmake \
-             -DCMAKE_BUILD_TYPE=Release \
-             -DFLATC=$(which flatc)
-    make
+```sh
+mkdir build
+cd build
+cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw64.cmake \
+            -DCMAKE_BUILD_TYPE=Release
+make
+```
 
-The graphical interface is built as `build/bin/solvespace.exe`, and the command-line interface
-is built as `build/bin/solvespace-cli.exe`.
+The graphical interface is built as `build/bin/solvespace.exe`, and the
+command-line interface is built as `build/bin/solvespace-cli.exe`.
 
 Space Navigator support will not be available.
 
-If using Ubuntu to cross-compile, Ubuntu 17.10 or newer (or, alternatively, MinGW from the Ubuntu
-17.10 repositories) is required.
+## Building on macOS
 
-Building on macOS
------------------
-
-You will need git, XCode tools and CMake. Git and CMake can be installed
+You will need git, XCode tools, CMake and libomp. Git, CMake and libomp can be installed
 via [Homebrew][]:
 
-    brew install git cmake
+```sh
+brew install git cmake libomp
+```
 
 XCode has to be installed via AppStore or [the Apple website][appledeveloper];
 it requires a free Apple ID.
 
 Before building, check out the project and the necessary submodules:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init
+```sh
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init
+```
 
 After that, build SolveSpace as following:
 
-    mkdir build
-    cd build
-    cmake .. -DCMAKE_BUILD_TYPE=Release
-    make
+```sh
+mkdir build
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_OPENMP=ON
+make
+```
+
+Link Time Optimization is supported by adding `-DENABLE_LTO=ON` to cmake at the
+expense of longer build time.
 
 Alternatively, generate an XCode project, open it, and build the "Release" scheme:
 
-    mkdir build
-    cd build
-    cmake .. -G Xcode
+```sh
+mkdir build
+cd build
+cmake .. -G Xcode
+```
 
 The application is built in `build/bin/SolveSpace.app`, the graphical interface executable
 is `build/bin/SolveSpace.app/Contents/MacOS/SolveSpace`, and the command-line interface executable
@@ -170,26 +207,32 @@ is `build/bin/SolveSpace.app/Contents/MacOS/solvespace-cli`.
 [homebrew]: https://brew.sh/
 [appledeveloper]: https://developer.apple.com/download/
 
-Building on OpenBSD
--------------------
+## Building on OpenBSD
 
 You will need git, cmake, libexecinfo, libpng, gtk3mm and pangomm.
 These can be installed from the ports tree:
 
-    pkg_add -U git cmake libexecinfo png json-c gtk3mm pangomm
+```sh
+pkg_add -U git cmake libexecinfo png json-c gtk3mm pangomm
+```
 
 Before building, check out the project and the necessary submodules:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init extlib/libdxfrw extlib/mimalloc
+```sh
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init extlib/libdxfrw extlib/mimalloc extlib/eigen
+```
 
 After that, build SolveSpace as following:
 
-    mkdir build
-    cd build
-    cmake .. -DCMAKE_BUILD_TYPE=Release
-    make
+```sh
+mkdir build
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release
+make
+sudo make install
+```
 
 Unfortunately, on OpenBSD, the produced executables are not filesystem location independent
 and must be installed before use. By default, the graphical interface is installed to
@@ -197,12 +240,13 @@ and must be installed before use. By default, the graphical interface is install
 `/usr/local/bin/solvespace-cli`. It is possible to build only the command-line interface
 by passing the `-DENABLE_GUI=OFF` flag to the cmake invocation.
 
-Building on Windows
--------------------
+## Building on Windows
 
 You will need [git][gitwin], [cmake][cmakewin] and a C++ compiler
 (either Visual C++ or MinGW). If using Visual C++, Visual Studio 2015
 or later is required.
+If gawk is in your path be sure it is a proper Windows port that can handle CL LF line endings.
+If not CMake may fail in libpng due to some awk scripts - issue #1228.
 
 ### Building with Visual Studio IDE
 
@@ -213,17 +257,19 @@ Visual C++ and build it.
 
 ### Building with Visual Studio in a command prompt
 
-First, ensure that git and cl (the Visual C++ compiler driver) are in your
+First, ensure that `git` and `cl` (the Visual C++ compiler driver) are in your
 `%PATH%`; the latter is usually done by invoking `vcvarsall.bat` from your
 Visual Studio install. Then, run the following in cmd or PowerShell:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init
-    mkdir build
-    cd build
-    cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
-    nmake
+```bat
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init
+mkdir build
+cd build
+cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
+nmake
+```
 
 ### Building with MinGW
 
@@ -233,25 +279,25 @@ Space Navigator support will be disabled.
 First, ensure that git and gcc are in your `$PATH`. Then, run the following
 in bash:
 
-    git clone https://github.com/solvespace/solvespace
-    cd solvespace
-    git submodule update --init
-    mkdir build
-    cd build
-    cmake .. -DCMAKE_BUILD_TYPE=Release
-    make
+```sh
+git clone https://github.com/solvespace/solvespace
+cd solvespace
+git submodule update --init
+mkdir build
+cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release
+make
+```
 
 [gitwin]: https://git-scm.com/download/win
 [cmakewin]: http://www.cmake.org/download/#latest
 [mingw]: http://www.mingw.org/
 
-Contributing
-------------
+## Contributing
 
 See the [guide for contributors](CONTRIBUTING.md) for the best way to file issues, contribute code,
 and debug SolveSpace.
 
-License
--------
+## License
 
-SolveSpace is distributed under the terms of the [GPL v3 license](COPYING.txt).
+SolveSpace is distributed under the terms of the [GPL v3](COPYING.txt) or later.
index fb6073c323c94f08e4941a5af5fc8c1ea50cd035..451063c6746e2235ce2a20efe06c62d86ec09eda 100644 (file)
@@ -16,7 +16,7 @@ if(UNIX)
 
     # Support the REQUIRED and QUIET arguments, and set SPACEWARE_FOUND if found.
     include(FindPackageHandleStandardArgs)
-    FIND_PACKAGE_HANDLE_STANDARD_ARGS(SPACEWARE DEFAULT_MSG
+    find_package_handle_standard_args(SpaceWare DEFAULT_MSG
         SPACEWARE_LIBRARY SPACEWARE_INCLUDE_DIR)
 
     if(SPACEWARE_FOUND)
index 668d1f7edcfa46f145ab072d63f23a71cecd36a7..b39a9e21059cbe9899e854f7d03fd03e29f90856 100644 (file)
         <key>CFBundlePackageType</key>
         <string>APPL</string>
         <key>CFBundleVersion</key>
-        <string>${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}~${solvespace_GIT_HASH}</string>
+        <string>${PROJECT_VERSION}~${solvespace_GIT_HASH}</string>
         <key>CFBundleShortVersionString</key>
-        <string>${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}</string>
+        <string>${PROJECT_VERSION}</string>
         <key>NSHumanReadableCopyright</key>
-        <string>© 2008-2016 Jonathan Westhues and other authors</string>
+        <string>© 2008-2022 Jonathan Westhues and other authors</string>
         <key>NSPrincipalClass</key>
         <string>NSApplication</string>
         <key>NSMainNibFile</key>
diff --git a/cmake/libpng-macos-arm64.patch b/cmake/libpng-macos-arm64.patch
new file mode 100644 (file)
index 0000000..2d0e15c
--- /dev/null
@@ -0,0 +1,117 @@
+diff --git a/extlib/libpng/CMakeLists.txt b/extlib/libpng/CMakeLists.txt
+index 42ff0f9025..6834ea332e 100644
+--- a/extlib/libpng/CMakeLists.txt
++++ b/extlib/libpng/CMakeLists.txt
+@@ -65,11 +65,22 @@ option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON)
+ set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names")
+ set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings")
++# CMake currently sets CMAKE_SYSTEM_PROCESSOR to one of x86_64 or arm64 on macOS,
++# based upon the OS architecture, not the target architecture. As such, we need
++# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to
++# enable. Note that this will fail if you attempt to build a universal binary in
++# a single cmake invocation.
++if (APPLE AND CMAKE_OSX_ARCHITECTURES)
++  set(TARGET_ARCH ${CMAKE_OSX_ARCHITECTURES})
++else()
++  set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
++endif()
++
+ if(PNG_HARDWARE_OPTIMIZATIONS)
+ # Set definitions and sources for ARM.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
+-  CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
++if(TARGET_ARCH MATCHES "^arm" OR
++  TARGET_ARCH MATCHES "^aarch64")
+   set(PNG_ARM_NEON_POSSIBLE_VALUES check on off)
+   set(PNG_ARM_NEON "check"
+       CACHE STRING "Enable ARM NEON optimizations: check|on|off; check is default")
+@@ -95,8 +106,8 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
+ endif()
+ # Set definitions and sources for PowerPC.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*")
++if(TARGET_ARCH MATCHES "^powerpc*" OR
++   TARGET_ARCH MATCHES "^ppc64*")
+   set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off)
+   set(PNG_POWERPC_VSX "on"
+       CACHE STRING "Enable POWERPC VSX optimizations: on|off; on is default")
+@@ -118,8 +129,8 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
+ endif()
+ # Set definitions and sources for Intel.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*")
++if(TARGET_ARCH MATCHES "^i?86" OR
++   TARGET_ARCH MATCHES "^x86_64*")
+   set(PNG_INTEL_SSE_POSSIBLE_VALUES on off)
+   set(PNG_INTEL_SSE "on"
+       CACHE STRING "Enable INTEL_SSE optimizations: on|off; on is default")
+@@ -141,8 +152,8 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
+ endif()
+ # Set definitions and sources for MIPS.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*")
++if(TARGET_ARCH MATCHES "mipsel*" OR
++   TARGET_ARCH MATCHES "mips64el*")
+   set(PNG_MIPS_MSA_POSSIBLE_VALUES on off)
+   set(PNG_MIPS_MSA "on"
+       CACHE STRING "Enable MIPS_MSA optimizations: on|off; on is default")
+@@ -166,26 +177,26 @@ endif()
+ else(PNG_HARDWARE_OPTIMIZATIONS)
+ # Set definitions and sources for ARM.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
++if(TARGET_ARCH MATCHES "^arm" OR
++   TARGET_ARCH MATCHES "^aarch64")
+   add_definitions(-DPNG_ARM_NEON_OPT=0)
+ endif()
+ # Set definitions and sources for PowerPC.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*")
++if(TARGET_ARCH MATCHES "^powerpc*" OR
++   TARGET_ARCH MATCHES "^ppc64*")
+   add_definitions(-DPNG_POWERPC_VSX_OPT=0)
+ endif()
+ # Set definitions and sources for Intel.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*")
++if(TARGET_ARCH MATCHES "^i?86" OR
++   TARGET_ARCH MATCHES "^x86_64*")
+   add_definitions(-DPNG_INTEL_SSE_OPT=0)
+ endif()
+ # Set definitions and sources for MIPS.
+-if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR
+-   CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*")
++if(TARGET_ARCH MATCHES "mipsel*" OR
++   TARGET_ARCH MATCHES "mips64el*")
+   add_definitions(-DPNG_MIPS_MSA_OPT=0)
+ endif()
+
+@@ -412,19 +412,11 @@ else()
+                DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk"
+                        "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
+-  add_custom_target(symbol-check
+-                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
+-
+   generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
+                 "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
+   generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
+                 "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
+
+-  add_custom_target(genvers
+-                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
+-  add_custom_target(gensym
+-                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
+-
+   add_custom_target("genprebuilt"
+                     COMMAND "${CMAKE_COMMAND}"
+                             "-DOUTPUT=scripts/pnglibconf.h.prebuilt"
diff --git a/developer_docs/IdLists_Entities_and_Remap.txt b/developer_docs/IdLists_Entities_and_Remap.txt
new file mode 100644 (file)
index 0000000..5fe1791
--- /dev/null
@@ -0,0 +1,49 @@
+Some notes about Entities, Entity IDs and the IdList structure
+==============================================================
+Sketch entities in SolveSpace are all of the same type without use of language
+support for polymorphism. The entity class is defined in sketch.h. That class
+contains an enum for each entity to define its type (line, arc, etc...) and some
+other members that can be used to store different things depending on the entity
+type. This means all entities are the same size, so some data may be reference
+by pointers from the entity (font, extra points, etc...)
+
+Entities in a sketch are kept in a global array (IdList) referenced by a unique
+Id (handle) and can be looked up by Id in log(n) time via binary search. In
+order to use binary search the array must be kept in order sorted by Id. One
+problem is that insertion takes O(n) time because half the list (on average)
+must be shifted to make room for a new item.
+
+The IdList class is a template and is used for more than entities.
+
+EntityMap:
+==========
+Another important structure is the EntityMap and EntityKey defined in sketch.h
+This is what allows SovleSpace to update groups when earlier groups in the
+sketch are changed. If a rectangle is extruded to a box and items are
+constrained to entities on that box, the user can go back to the sketch and
+modify it. Entities can be added, modified an even deleted. So long as the
+entities that are later used to build upon are kept the later extrude group will
+pick up the changes from the 2D sketch and anything build on it will remain.
+
+The way this works is that each group has a member called remap, which is one of
+these maps. This is where my understanding is fuzzy. At the end of Group.cpp is
+a function called Group::CopyEntity() which is used to make new sketch entities
+when a group is created. These are generally copies of entities in the previous
+group, but there are exceptions. A point will be used to generate a line when
+extruding a 2D sketch. A point will also be "copied" to a circle for a Lathe
+group. For this reason, the entity key is derived by combining its previous key
+with something often called the CopyNumber or just remap (unfortunate).
+
+When a group is regenerated (the first time, or after a previous one is
+modified) entities are copied from the old group to the new one. For Step
+Translating and Rotating there may be many copies, and the copy number is
+literally N for the Nth copy except for the last one which gets an enum - it is
+common to constrain the last item, so it gets a large unique number so that
+constraints still refer to it if the number of copies changes. When an entity is
+copied like this a new handle is created unless there is already an entity in
+Remap that was created the same way. This is how constructions are preserved
+across underlying changes.
+
+There are some hard limits used in the hash table for the remap mechanism which
+limit the number of entities in a group (but not the global sketch).
+
index 1ea3ae5f205e41f6cdf198feb3fd90a9773fc2b0..98300f8b12f673f791b294d01035448edf51146e 100644 (file)
@@ -46,7 +46,7 @@ POINT_N_ROT_TRANS: Rotates a point via quaternion param[3],param[4],param[5],par
 
 POINT_N_COPY:      A non-transformed copy of a point - numeric copy?
 
-POINT_N_ROT_AA:    A point rotated arount point param[0],param[1],param[2] Where the
+POINT_N_ROT_AA:    A point rotated around point param[0],param[1],param[2] Where the
                    angle is given by param[3]*timesApplied (times 2?) and the axis
                    of rotation defined by param[4],param[5],param[6]
 
@@ -130,7 +130,7 @@ the entity itself.
 The ForceTo() functions are shortcuts for using the solver. They are passed the
 desired location of a point (or orientation of a normal...) and have the opportunity
 to back-calculate what the group parameters should be to place it there. This is
-used for mouse dragging of copied entites. It is notable that the constraints will
+used for mouse dragging of copied entities. It is notable that the constraints will
 still be applied afterward, but this is a good shortcut.
 
 When creating a new entity transformation, the first thing to do is define the
diff --git a/extlib/mimalloc/.gitattributes b/extlib/mimalloc/.gitattributes
deleted file mode 100644 (file)
index acdbdbf..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# default behavior is to always use unix style line endings
-* text eol=lf
-*.png binary
-*.pdn binary
-*.sln binary
-*.suo binary
-*.vcproj binary
-*.patch binary
-*.dll binary
-*.lib binary
diff --git a/extlib/mimalloc/.gitignore b/extlib/mimalloc/.gitignore
deleted file mode 100644 (file)
index 3639d32..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-ide/vs20??/*.db
-ide/vs20??/*.opendb
-ide/vs20??/*.user
-ide/vs20??/*.vcxproj.filters
-ide/vs20??/.vs
-out/
-docs/
-*.zip
index 37616eb4d425914d2224e7e29d9952a34980b83e..8127e0965c023f133dc344a540e80745576b384c 100644 (file)
@@ -12,8 +12,8 @@ option(MI_XMALLOC           "Enable abort() call on memory allocation failure by
 option(MI_SHOW_ERRORS       "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF)
 option(MI_USE_CXX           "Use the C++ compiler to compile the library (instead of the C compiler)" OFF)
 option(MI_SEE_ASM           "Generate assembly files" OFF)
-option(MI_INTERPOSE         "Use interpose to override standard malloc on macOS" ON)
-option(MI_OSX_ZONE          "Use malloc zone to override standard malloc on macOS" OFF) # enables interpose as well
+option(MI_OSX_INTERPOSE     "Use interpose to override standard malloc on macOS" ON)
+option(MI_OSX_ZONE          "Use malloc zone to override standard malloc on macOS" ON) 
 option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF)
 option(MI_BUILD_SHARED      "Build shared library" ON)
 option(MI_BUILD_STATIC      "Build static library" ON)
@@ -21,16 +21,23 @@ option(MI_BUILD_OBJECT      "Build object library" ON)
 option(MI_BUILD_TESTS       "Build test executables" ON)
 option(MI_DEBUG_TSAN        "Build with thread sanitizer (needs clang)" OFF)
 option(MI_DEBUG_UBSAN       "Build with undefined-behavior sanitizer (needs clang++)" OFF)
+option(MI_SKIP_COLLECT_ON_EXIT, "Skip collecting memory on program exit" OFF)
+
+# deprecated options
 option(MI_CHECK_FULL        "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF)
+option(MI_INSTALL_TOPLEVEL  "Install directly into $CMAKE_INSTALL_PREFIX instead of PREFIX/lib/mimalloc-version (deprecated)" OFF)
+option(MI_USE_LIBATOMIC     "Explicitly link with -latomic (on older systems) (deprecated and detected automatically)" OFF)
 
+include(GNUInstallDirs)
 include("cmake/mimalloc-config-version.cmake")
 
 set(mi_sources
     src/stats.c
     src/random.c
     src/os.c
+    src/bitmap.c
     src/arena.c
-    src/region.c
+    src/segment-cache.c
     src/segment.c
     src/page.c
     src/alloc.c
@@ -40,12 +47,14 @@ set(mi_sources
     src/options.c
     src/init.c)
 
+
 # -----------------------------------------------------------------------------
-# Converience: set default build type depending on the build directory
+# Convenience: set default build type depending on the build directory
 # -----------------------------------------------------------------------------
 
+message(STATUS "")    
 if (NOT CMAKE_BUILD_TYPE)
-  if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR  MI_DEBUG_FULL MATCHES "ON")
+  if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR  MI_DEBUG_FULL)
     message(STATUS "No build type selected, default to: Debug")
     set(CMAKE_BUILD_TYPE "Debug")
   else()
@@ -59,6 +68,7 @@ if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$")
   set(MI_SECURE "ON")
 endif()
 
+
 # -----------------------------------------------------------------------------
 # Process options
 # -----------------------------------------------------------------------------
@@ -67,65 +77,76 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel")
   set(MI_USE_CXX "ON")
 endif()
 
-if(MI_OVERRIDE MATCHES "ON")
+if(MI_OVERRIDE)
   message(STATUS "Override standard malloc (MI_OVERRIDE=ON)")
   if(APPLE)
-    if(MI_OSX_ZONE MATCHES "ON")
+    if(MI_OSX_ZONE)
       # use zone's on macOS
       message(STATUS "  Use malloc zone to override malloc (MI_OSX_ZONE=ON)")
       list(APPEND mi_sources src/alloc-override-osx.c)
-      list(APPEND mi_defines MI_OSX_ZONE=1)
-      if(NOT MI_INTERPOSE MATCHES "ON")
-        message(STATUS "  (enabling INTERPOSE as well since zone's require this)")
-        set(MI_INTERPOSE "ON")
+      list(APPEND mi_defines MI_OSX_ZONE=1)      
+      if (NOT MI_OSX_INTERPOSE)
+        message(STATUS "  WARNING: zone overriding usually also needs interpose (use -DMI_OSX_INTERPOSE=ON)")
       endif()
     endif()
-    if(MI_INTERPOSE MATCHES "ON")
+    if(MI_OSX_INTERPOSE)
       # use interpose on macOS
-      message(STATUS "  Use interpose to override malloc (MI_INTERPOSE=ON)")
-      list(APPEND mi_defines MI_INTERPOSE)
+      message(STATUS "  Use interpose to override malloc (MI_OSX_INTERPOSE=ON)")
+      list(APPEND mi_defines MI_OSX_INTERPOSE=1)
+      if (NOT MI_OSX_ZONE)
+        message(STATUS "  WARNING: interpose usually also needs zone overriding (use -DMI_OSX_INTERPOSE=ON)")
+      endif()
+    endif()
+    if(MI_USE_CXX AND MI_OSX_INTERPOSE)
+      message(STATUS "  WARNING: if dynamically overriding malloc/free, it is more reliable to build mimalloc as C code (use -DMI_USE_CXX=OFF)")
     endif()
   endif()
 endif()
 
-if(MI_SECURE MATCHES "ON")
+if(MI_SECURE)
   message(STATUS "Set full secure build (MI_SECURE=ON)")
   list(APPEND mi_defines MI_SECURE=4)
 endif()
 
-if(MI_SEE_ASM MATCHES "ON")
+if(MI_SEE_ASM)
   message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)")
   list(APPEND mi_cflags -save-temps)
 endif()
 
-if(MI_CHECK_FULL MATCHES "ON")
+if(MI_CHECK_FULL)
   message(STATUS "The MI_CHECK_FULL option is deprecated, use MI_DEBUG_FULL instead")
   set(MI_DEBUG_FULL "ON")
 endif()
 
-if(MI_DEBUG_FULL MATCHES "ON")
+if (MI_SKIP_COLLECT_ON_EXIT)
+  message(STATUS "Skip collecting memory on program exit (MI_SKIP_COLLECT_ON_EXIT=ON)")
+  list(APPEND mi_defines MI_SKIP_COLLECT_ON_EXIT=1)
+endif()
+
+if(MI_DEBUG_FULL)
   message(STATUS "Set debug level to full internal invariant checking (MI_DEBUG_FULL=ON)")
   list(APPEND mi_defines MI_DEBUG=3)   # full invariant checking
 endif()
 
-if(MI_PADDING MATCHES "OFF")
+if(NOT MI_PADDING)
   message(STATUS "Disable padding of heap blocks in debug mode (MI_PADDING=OFF)")
   list(APPEND mi_defines MI_PADDING=0)
 endif()
 
-if(MI_XMALLOC MATCHES "ON")
+if(MI_XMALLOC)
   message(STATUS "Enable abort() calls on memory allocation failure (MI_XMALLOC=ON)")
   list(APPEND mi_defines MI_XMALLOC=1)
 endif()
 
-if(MI_SHOW_ERRORS MATCHES "ON")
+if(MI_SHOW_ERRORS)
   message(STATUS "Enable printing of error and warning messages by default (MI_SHOW_ERRORS=ON)")
   list(APPEND mi_defines MI_SHOW_ERRORS=1)
 endif()
 
-if(MI_DEBUG_TSAN MATCHES "ON") 
+if(MI_DEBUG_TSAN)
   if(CMAKE_C_COMPILER_ID MATCHES "Clang")
     message(STATUS "Build with thread sanitizer (MI_DEBUG_TSAN=ON)")
+    list(APPEND mi_defines MI_TSAN=1)
     list(APPEND mi_cflags -fsanitize=thread -g -O1)
     list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=thread)
   else()
@@ -133,13 +154,13 @@ if(MI_DEBUG_TSAN MATCHES "ON")
   endif()  
 endif()
 
-if(MI_DEBUG_UBSAN MATCHES "ON") 
+if(MI_DEBUG_UBSAN)
   if(CMAKE_BUILD_TYPE MATCHES "Debug")    
     if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
       message(STATUS "Build with undefined-behavior sanitizer (MI_DEBUG_UBSAN=ON)")
-      list(APPEND mi_cflags -fsanitize=undefined -g)
+      list(APPEND mi_cflags -fsanitize=undefined -g -fno-sanitize-recover=undefined)
       list(APPEND CMAKE_EXE_LINKER_FLAGS -fsanitize=undefined)
-      if (MI_USE_CXX MATCHES "OFF")
+      if (NOT MI_USE_CXX)
         message(STATUS "(switch to use C++ due to MI_DEBUG_UBSAN)")
         set(MI_USE_CXX "ON")
       endif()
@@ -151,10 +172,10 @@ if(MI_DEBUG_UBSAN MATCHES "ON")
   endif()
 endif()
 
-if(MI_USE_CXX MATCHES "ON")
+if(MI_USE_CXX)
   message(STATUS "Use the C++ compiler to compile (MI_USE_CXX=ON)")
   set_source_files_properties(${mi_sources} PROPERTIES LANGUAGE CXX )
-  set_source_files_properties(src/static.c test/test-api.c test/test-stress PROPERTIES LANGUAGE CXX )
+  set_source_files_properties(src/static.c test/test-api.c test/test-api-fill test/test-stress PROPERTIES LANGUAGE CXX )
   if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang|Clang")
     list(APPEND mi_cflags -Wno-deprecated)
   endif()
@@ -166,8 +187,11 @@ endif()
 # Compiler flags
 if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
   list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden)
-  if(CMAKE_C_COMPILER_ID MATCHES "GNU")
-    list(APPEND mi_cflags -Wno-invalid-memory-model)
+  if(NOT MI_USE_CXX)
+    list(APPEND mi_cflags -Wstrict-prototypes)
+  endif()  
+  if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang")
+    list(APPEND mi_cflags -Wpedantic -Wno-static-in-inline)
   endif()
 endif()
 
@@ -176,28 +200,35 @@ if(CMAKE_C_COMPILER_ID MATCHES "Intel")
 endif()
 
 if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel" AND NOT CMAKE_SYSTEM_NAME MATCHES "Haiku")
-  if(MI_LOCAL_DYNAMIC_TLS MATCHES "ON")
+  if(MI_LOCAL_DYNAMIC_TLS)
     list(APPEND mi_cflags -ftls-model=local-dynamic)
   else()
     list(APPEND mi_cflags -ftls-model=initial-exec)
   endif()
+  if(MI_OVERRIDE)
+    list(APPEND mi_cflags -fno-builtin-malloc)
+  endif()
 endif()
 
-# Architecture flags
-if(${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm")
-    list(APPEND mi_cflags -march=native)
+if (MSVC AND MSVC_VERSION GREATER_EQUAL 1914)
+  list(APPEND mi_cflags /Zc:__cplusplus)
 endif()
 
 # extra needed libraries
 if(WIN32)
-  list(APPEND mi_libraries psapi shell32 user32 bcrypt)
+  list(APPEND mi_libraries psapi shell32 user32 advapi32 bcrypt)
 else()
-  if(NOT ${CMAKE_C_COMPILER} MATCHES "android")
-    list(APPEND mi_libraries pthread)
-    find_library(LIBRT rt)
-    if(LIBRT)
-      list(APPEND mi_libraries ${LIBRT})
-    endif()
+  find_library(MI_LIBPTHREAD pthread)
+  if (MI_LIBPTHREAD)                      
+    list(APPEND mi_libraries ${MI_LIBPTHREAD})
+  endif()
+  find_library(MI_LIBRT rt)
+  if(MI_LIBRT)
+    list(APPEND mi_libraries ${MI_LIBRT})
+  endif()  
+  find_library(MI_LIBATOMIC atomic)
+  if (MI_LIBATOMIC OR MI_USE_LIBATOMIC) 
+    list(APPEND mi_libraries atomic)
   endif()
 endif()
 
@@ -205,14 +236,29 @@ endif()
 # Install and output names
 # -----------------------------------------------------------------------------
 
-set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}")
-if(MI_SECURE MATCHES "ON")
+# dynamic/shared library and symlinks always go to /usr/local/lib equivalent
+set(mi_install_libdir   "${CMAKE_INSTALL_LIBDIR}")
+
+# static libraries and object files, includes, and cmake config files
+# are either installed at top level, or use versioned directories for side-by-side installation (default)
+if (MI_INSTALL_TOPLEVEL)
+  set(mi_install_objdir     "${CMAKE_INSTALL_LIBDIR}")
+  set(mi_install_incdir     "${CMAKE_INSTALL_INCLUDEDIR}")        
+  set(mi_install_cmakedir   "${CMAKE_INSTALL_LIBDIR}/cmake/mimalloc")
+else()
+  set(mi_install_objdir     "${CMAKE_INSTALL_LIBDIR}/mimalloc-${mi_version}")       # for static library and object files
+  set(mi_install_incdir     "${CMAKE_INSTALL_INCLUDEDIR}/mimalloc-${mi_version}")   # for includes
+  set(mi_install_cmakedir   "${CMAKE_INSTALL_LIBDIR}/cmake/mimalloc-${mi_version}") # for cmake package info
+endif()
+
+if(MI_SECURE)
   set(mi_basename "mimalloc-secure")
 else()
   set(mi_basename "mimalloc")
 endif()
+
 string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC)
-if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel)$"))
+if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel|none)$"))
   set(mi_basename "${mi_basename}-${CMAKE_BUILD_TYPE_LC}") #append build type (e.g. -debug) if not a release version
 endif()
 if(MI_BUILD_SHARED)
@@ -227,10 +273,19 @@ endif()
 if(MI_BUILD_TESTS)
   list(APPEND mi_build_targets "tests")
 endif()
+
 message(STATUS "")
 message(STATUS "Library base name: ${mi_basename}")
+message(STATUS "Version          : ${mi_version}")
 message(STATUS "Build type       : ${CMAKE_BUILD_TYPE_LC}")
-message(STATUS "Install directory: ${mi_install_dir}")
+if(MI_USE_CXX)
+  message(STATUS "C++ Compiler     : ${CMAKE_CXX_COMPILER}")
+else()
+  message(STATUS "C Compiler       : ${CMAKE_C_COMPILER}")
+endif()
+message(STATUS "Compiler flags   : ${mi_cflags}")
+message(STATUS "Compiler defines : ${mi_defines}")
+message(STATUS "Link libraries   : ${mi_libraries}")
 message(STATUS "Build targets    : ${mi_build_targets}")
 message(STATUS "")
 
@@ -241,24 +296,31 @@ message(STATUS "")
 # shared library
 if(MI_BUILD_SHARED)
   add_library(mimalloc SHARED ${mi_sources})
-  set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} OUTPUT_NAME ${mi_basename} )
+  set_target_properties(mimalloc PROPERTIES VERSION ${mi_version} SOVERSION ${mi_version_major} OUTPUT_NAME ${mi_basename} )
   target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_SHARED_LIB MI_SHARED_LIB_EXPORT)
   target_compile_options(mimalloc PRIVATE ${mi_cflags})
   target_link_libraries(mimalloc PUBLIC ${mi_libraries})
   target_include_directories(mimalloc PUBLIC
       $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-      $<INSTALL_INTERFACE:${mi_install_dir}/include>
+      $<INSTALL_INTERFACE:${mi_install_incdir}>
   )
   if(WIN32)
     # On windows copy the mimalloc redirection dll too.
-    target_link_libraries(mimalloc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect.lib)
+    if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+      set(MIMALLOC_REDIRECT_SUFFIX "32")
+    else()
+      set(MIMALLOC_REDIRECT_SUFFIX "")
+    endif()
+
+    target_link_libraries(mimalloc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect${MIMALLOC_REDIRECT_SUFFIX}.lib)
     add_custom_command(TARGET mimalloc POST_BUILD
-      COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect.dll" $<TARGET_FILE_DIR:mimalloc>
-      COMMENT "Copy mimalloc-redirect.dll to output directory")
+      COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/bin/mimalloc-redirect${MIMALLOC_REDIRECT_SUFFIX}.dll" $<TARGET_FILE_DIR:mimalloc>
+      COMMENT "Copy mimalloc-redirect${MIMALLOC_REDIRECT_SUFFIX}.dll to output directory")
+    install(FILES "$<TARGET_FILE_DIR:mimalloc>/mimalloc-redirect${MIMALLOC_REDIRECT_SUFFIX}.dll" DESTINATION ${mi_install_libdir})
   endif()
 
-  install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_dir} LIBRARY)
-  install(EXPORT mimalloc DESTINATION ${mi_install_dir}/cmake)
+  install(TARGETS mimalloc EXPORT mimalloc DESTINATION ${mi_install_libdir} LIBRARY)  
+  install(EXPORT mimalloc DESTINATION ${mi_install_cmakedir})
 endif()
 
 # static library
@@ -270,7 +332,7 @@ if (MI_BUILD_STATIC)
   target_link_libraries(mimalloc-static PUBLIC ${mi_libraries})
   target_include_directories(mimalloc-static PUBLIC
       $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-      $<INSTALL_INTERFACE:${mi_install_dir}/include>
+      $<INSTALL_INTERFACE:${mi_install_incdir}>
   )
   if(WIN32)
     # When building both static and shared libraries on Windows, a static library should use a
@@ -281,23 +343,17 @@ if (MI_BUILD_STATIC)
     set_target_properties(mimalloc-static PROPERTIES OUTPUT_NAME ${mi_basename})
   endif()
 
-  install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_dir})
+  install(TARGETS mimalloc-static EXPORT mimalloc DESTINATION ${mi_install_objdir} LIBRARY)
+  install(EXPORT mimalloc DESTINATION ${mi_install_cmakedir})
 endif()
 
 # install include files
-install(FILES include/mimalloc.h DESTINATION ${mi_install_dir}/include)
-install(FILES include/mimalloc-override.h DESTINATION ${mi_install_dir}/include)
-install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_dir}/include)
-install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_dir}/cmake)
-install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_dir}/cmake)
+install(FILES include/mimalloc.h DESTINATION ${mi_install_incdir})
+install(FILES include/mimalloc-override.h DESTINATION ${mi_install_incdir})
+install(FILES include/mimalloc-new-delete.h DESTINATION ${mi_install_incdir})
+install(FILES cmake/mimalloc-config.cmake DESTINATION ${mi_install_cmakedir})
+install(FILES cmake/mimalloc-config-version.cmake DESTINATION ${mi_install_cmakedir})
 
-if(NOT WIN32 AND MI_BUILD_SHARED)
-  # install a symlink in the /usr/local/lib to the versioned library
-  set(mi_symlink "${CMAKE_SHARED_MODULE_PREFIX}${mi_basename}${CMAKE_SHARED_LIBRARY_SUFFIX}")
-  set(mi_soname "mimalloc-${mi_version}/${mi_symlink}.${mi_version}")
-  install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${mi_soname} ${mi_symlink} WORKING_DIRECTORY ${mi_install_dir}/..)")
-  install(CODE "MESSAGE(\"-- Symbolic link: ${CMAKE_INSTALL_PREFIX}/lib/${mi_symlink} -> ${mi_soname}\")")
-endif()
 
 # single object file for more predictable static overriding
 if (MI_BUILD_OBJECT)
@@ -307,16 +363,16 @@ if (MI_BUILD_OBJECT)
   target_compile_options(mimalloc-obj PRIVATE ${mi_cflags})
   target_include_directories(mimalloc-obj PUBLIC
       $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-      $<INSTALL_INTERFACE:${mi_install_dir}/include>
+      $<INSTALL_INTERFACE:${mi_install_incdir}>
   )
 
   # the following seems to lead to cmake warnings/errors on some systems, disable for now :-(
-  # install(TARGETS mimalloc-obj EXPORT mimalloc DESTINATION ${mi_install_dir})
+  # install(TARGETS mimalloc-obj EXPORT mimalloc DESTINATION ${mi_install_objdir})
 
   # the FILES expression can also be: $<TARGET_OBJECTS:mimalloc-obj>
   # but that fails cmake versions less than 3.10 so we leave it as is for now
   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/mimalloc-obj.dir/src/static.c${CMAKE_C_OUTPUT_EXTENSION}
-          DESTINATION ${mi_install_dir}
+          DESTINATION ${mi_install_objdir}
           RENAME ${mi_basename}${CMAKE_C_OUTPUT_EXTENSION} )
 endif()
 
@@ -324,28 +380,24 @@ endif()
 # API surface testing
 # -----------------------------------------------------------------------------
 
-if (MI_BUILD_TESTS MATCHES "ON")
-  add_executable(mimalloc-test-api test/test-api.c)
-  target_compile_definitions(mimalloc-test-api PRIVATE ${mi_defines})
-  target_compile_options(mimalloc-test-api PRIVATE ${mi_cflags})
-  target_include_directories(mimalloc-test-api PRIVATE include)
-  target_link_libraries(mimalloc-test-api PRIVATE mimalloc-static ${mi_libraries})
+if (MI_BUILD_TESTS)
+  enable_testing()
 
-  add_executable(mimalloc-test-stress test/test-stress.c)
-  target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines})
-  target_compile_options(mimalloc-test-stress PRIVATE ${mi_cflags})
-  target_include_directories(mimalloc-test-stress PRIVATE include)
-  target_link_libraries(mimalloc-test-stress PRIVATE mimalloc ${mi_libraries})
+  foreach(TEST_NAME api api-fill stress)
+    add_executable(mimalloc-test-${TEST_NAME} test/test-${TEST_NAME}.c)
+    target_compile_definitions(mimalloc-test-${TEST_NAME} PRIVATE ${mi_defines})
+    target_compile_options(mimalloc-test-${TEST_NAME} PRIVATE ${mi_cflags})
+    target_include_directories(mimalloc-test-${TEST_NAME} PRIVATE include)
+    target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc ${mi_libraries})
 
-  enable_testing()
-  add_test(test_api, mimalloc-test-api)
-  add_test(test_stress, mimalloc-test-stress)
+    add_test(NAME test-${TEST_NAME} COMMAND mimalloc-test-${TEST_NAME})
+  endforeach()
 endif()
 
 # -----------------------------------------------------------------------------
 # Set override properties
 # -----------------------------------------------------------------------------
-if (MI_OVERRIDE MATCHES "ON")
+if (MI_OVERRIDE)
   if (MI_BUILD_SHARED)
     target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE)
   endif()
index 4151dbe4ab1d9752ca629747bb80b71b082381c0..670b668a0c928e5c29439d6dbf43091ed8932f56 100644 (file)
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2019 Microsoft Corporation, Daan Leijen
+Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
index c81e31bd499bbca92434afb878469296ab4aee03..c6efc87ac0fe07b6fc77249d8c3c86953b1d0693 100644 (file)
@@ -4,15 +4,21 @@
 # https://aka.ms/yaml
 
 trigger:
-- master
-- dev
+  branches:
+    include:
+    - master
+    - dev
+    - dev-slice
+  tags:
+    include:
+    - v*
 
-jobs:
+jobs:  
 - job:
   displayName: Windows
   pool:
     vmImage:
-     windows-2019
+      windows-2019
   strategy:
     matrix:
       Debug:
@@ -36,18 +42,20 @@ jobs:
     inputs:
       solution: $(BuildType)/libmimalloc.sln
       configuration: '$(MSBuildConfiguration)'
-  - script: |
-      cd $(BuildType)
-      ctest
+      msbuildArguments: -m
+  - script: ctest --verbose --timeout 120 -C $(MSBuildConfiguration)
+    workingDirectory: $(BuildType)
     displayName: CTest
-#  - upload: $(Build.SourcesDirectory)/$(BuildType)
-#    artifact: mimalloc-windows-$(BuildType)
+  #- script: $(BuildType)\$(BuildType)\mimalloc-test-stress
+  #  displayName: TestStress
+  #- upload: $(Build.SourcesDirectory)/$(BuildType)
+  #  artifact: mimalloc-windows-$(BuildType)
 
 - job:
   displayName: Linux
   pool:
     vmImage:
-     ubuntu-16.04
+     ubuntu-18.04
   strategy:
     matrix:
       Debug:
@@ -97,7 +105,8 @@ jobs:
       cmakeArgs: .. $(cmakeExtraArgs)
   - script: make -j$(nproc) -C $(BuildType)
     displayName: Make
-  - script: make test -C $(BuildType)
+  - script: ctest --verbose --timeout 120
+    workingDirectory: $(BuildType)
     displayName: CTest
 #  - upload: $(Build.SourcesDirectory)/$(BuildType)
 #    artifact: mimalloc-ubuntu-$(BuildType)
@@ -106,7 +115,7 @@ jobs:
   displayName: macOS
   pool:
     vmImage:
-     macOS-10.14
+      macOS-latest
   strategy:
     matrix:
       Debug:
@@ -125,7 +134,48 @@ jobs:
       cmakeArgs: .. $(cmakeExtraArgs)
   - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType)
     displayName: Make
-  - script: make test -C $(BuildType)
+  # - script: MIMALLOC_VERBOSE=1 ./mimalloc-test-api
+  #   workingDirectory: $(BuildType)
+  #   displayName: TestAPI
+  # - script: MIMALLOC_VERBOSE=1 ./mimalloc-test-stress
+  #   workingDirectory: $(BuildType)
+  #   displayName: TestStress    
+  - script: ctest --verbose --timeout 120
+    workingDirectory: $(BuildType)
     displayName: CTest
+    
 #  - upload: $(Build.SourcesDirectory)/$(BuildType)
 #    artifact: mimalloc-macos-$(BuildType)
+
+# - job:
+#   displayName: Windows-2017
+#   pool:
+#     vmImage:
+#       vs2017-win2016
+#   strategy:
+#     matrix:
+#       Debug:
+#         BuildType: debug
+#         cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
+#         MSBuildConfiguration: Debug
+#       Release:
+#         BuildType: release
+#         cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release
+#         MSBuildConfiguration: Release
+#       Secure:
+#         BuildType: secure
+#         cmakeExtraArgs: -A x64 -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
+#         MSBuildConfiguration: Release
+#   steps:
+#   - task: CMake@1
+#     inputs:
+#       workingDirectory: $(BuildType)
+#       cmakeArgs: .. $(cmakeExtraArgs)
+#   - task: MSBuild@1
+#     inputs:
+#       solution: $(BuildType)/libmimalloc.sln
+#       configuration: '$(MSBuildConfiguration)'
+#   - script: |
+#       cd $(BuildType)
+#       ctest --verbose --timeout 120
+#     displayName: CTest
diff --git a/extlib/mimalloc/bin/mimalloc-redirect.dll b/extlib/mimalloc/bin/mimalloc-redirect.dll
new file mode 100644 (file)
index 0000000..83b6bd4
Binary files /dev/null and b/extlib/mimalloc/bin/mimalloc-redirect.dll differ
diff --git a/extlib/mimalloc/bin/mimalloc-redirect.lib b/extlib/mimalloc/bin/mimalloc-redirect.lib
new file mode 100644 (file)
index 0000000..059fb87
Binary files /dev/null and b/extlib/mimalloc/bin/mimalloc-redirect.lib differ
diff --git a/extlib/mimalloc/bin/mimalloc-redirect32.dll b/extlib/mimalloc/bin/mimalloc-redirect32.dll
new file mode 100644 (file)
index 0000000..2892d45
Binary files /dev/null and b/extlib/mimalloc/bin/mimalloc-redirect32.dll differ
diff --git a/extlib/mimalloc/bin/mimalloc-redirect32.lib b/extlib/mimalloc/bin/mimalloc-redirect32.lib
new file mode 100644 (file)
index 0000000..7dadab3
Binary files /dev/null and b/extlib/mimalloc/bin/mimalloc-redirect32.lib differ
diff --git a/extlib/mimalloc/bin/minject.exe b/extlib/mimalloc/bin/minject.exe
new file mode 100644 (file)
index 0000000..625816f
Binary files /dev/null and b/extlib/mimalloc/bin/minject.exe differ
diff --git a/extlib/mimalloc/bin/minject32.exe b/extlib/mimalloc/bin/minject32.exe
new file mode 100644 (file)
index 0000000..6857ad0
Binary files /dev/null and b/extlib/mimalloc/bin/minject32.exe differ
index 6454d91fbb33546be92015a0f7eb24a4a255992e..8063afe6b96bd920ba25acac1326101ad1d25e9b 100644 (file)
@@ -1,16 +1,19 @@
-set(mi_version_major 1)
-set(mi_version_minor 6)
+set(mi_version_major 2)
+set(mi_version_minor 0)
+set(mi_version_patch 6)
 set(mi_version ${mi_version_major}.${mi_version_minor})
 
 set(PACKAGE_VERSION ${mi_version})
-if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "${mi_version_major}")
-    if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "${mi_version_minor}")
-        set(PACKAGE_VERSION_EXACT TRUE)
-    elseif("${PACKAGE_FIND_VERSION_MINOR}" LESS "${mi_version_minor}")
-        set(PACKAGE_VERSION_COMPATIBLE TRUE)
+if(PACKAGE_FIND_VERSION_MAJOR)
+    if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "${mi_version_major}")
+        if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "${mi_version_minor}")
+            set(PACKAGE_VERSION_EXACT TRUE)
+        elseif("${PACKAGE_FIND_VERSION_MINOR}" LESS "${mi_version_minor}")
+            set(PACKAGE_VERSION_COMPATIBLE TRUE)
+        else()
+            set(PACKAGE_VERSION_UNSUITABLE TRUE)
+        endif()
     else()
         set(PACKAGE_VERSION_UNSUITABLE TRUE)
     endif()
-else()
-    set(PACKAGE_VERSION_UNSUITABLE TRUE)
 endif()
index 12da076e314407905fba6205c72feac8cfdd74ae..8a28e37e7edd76c35ba9567e6a3c0bf335377c8b 100644 (file)
@@ -1,2 +1,14 @@
 include(${CMAKE_CURRENT_LIST_DIR}/mimalloc.cmake)
-get_filename_component(MIMALLOC_TARGET_DIR "${CMAKE_CURRENT_LIST_DIR}" PATH)
+get_filename_component(MIMALLOC_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}" PATH)  # one up from the cmake dir, e.g. /usr/local/lib/cmake/mimalloc-2.0
+get_filename_component(MIMALLOC_VERSION_DIR "${CMAKE_CURRENT_LIST_DIR}" NAME)
+string(REPLACE "/lib/cmake" "/lib" MIMALLOC_LIBRARY_DIR "${MIMALLOC_CMAKE_DIR}")
+if("${MIMALLOC_VERSION_DIR}" EQUAL "mimalloc")  
+  # top level install
+  string(REPLACE "/lib/cmake" "/include" MIMALLOC_INCLUDE_DIR "${MIMALLOC_CMAKE_DIR}")
+  set(MIMALLOC_OBJECT_DIR "${MIMALLOC_LIBRARY_DIR}")
+else()  
+  # versioned
+  string(REPLACE "/lib/cmake/" "/include/" MIMALLOC_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}")
+  string(REPLACE "/lib/cmake/" "/lib/" MIMALLOC_OBJECT_DIR "${CMAKE_CURRENT_LIST_DIR}")  
+endif()  
+set(MIMALLOC_TARGET_DIR "${MIMALLOC_LIBRARY_DIR}") # legacy
diff --git a/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg b/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg
new file mode 100644 (file)
index 0000000..9005097
--- /dev/null
@@ -0,0 +1,887 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='167.731pt' version='1.1' viewBox='52.938 54.996 381.624 167.731' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip1'>
+<path d='M82.148 206.586H434.164V81.34H82.148Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+</defs>
+<g id='page1'>
+<path d='M140.82 215.441V206.586M199.488 215.441V206.586M258.156 215.441V206.586M316.824 215.441V206.586M375.496 215.441V206.586M140.82 72.48V81.34M199.488 72.48V81.34M258.156 72.48V81.34M316.824 72.48V81.34M375.496 72.48V81.34' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 210.836V206.586M170.152 210.836V206.586M228.824 210.836V206.586M287.492 210.836V206.586M346.16 210.836V206.586M404.828 210.836V206.586M111.484 77.086V81.34M170.152 77.086V81.34M228.824 77.086V81.34M287.492 77.086V81.34M346.16 77.086V81.34M404.828 77.086V81.34' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 206.586H86.402M82.148 175.273H86.402M82.148 143.961H86.402M82.148 112.648H86.402M82.148 81.34H86.402M434.164 206.586H429.91M434.164 175.273H429.91M434.164 143.961H429.91M434.164 112.648H429.91M434.164 81.34H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 206.586V81.34H434.164V206.586H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' xlink:href='#g3-99' y='186.027'/>
+<use x='118.25' xlink:href='#g3-102' y='186.027'/>
+<use x='120.838' xlink:href='#g3-114' y='186.027'/>
+<use x='123.73' xlink:href='#g3-97' y='186.027'/>
+<use x='127.798' xlink:href='#g3-99' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='186.027'/>
+<use x='116.507' xlink:href='#g3-101' y='186.027'/>
+<use x='120.271' xlink:href='#g3-97' y='186.027'/>
+<use x='124.339' xlink:href='#g3-110' y='186.027'/>
+<use x='128.711' xlink:href='#g3-78' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='186.027'/>
+<use x='117.379' xlink:href='#g3-101' y='186.027'/>
+<use x='121.142' xlink:href='#g3-100' y='186.027'/>
+<use x='125.515' xlink:href='#g3-105' y='186.027'/>
+<use x='127.535' xlink:href='#g3-115' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='186.027'/>
+<use x='116.507' xlink:href='#g3-97' y='186.027'/>
+<use x='120.34' xlink:href='#g3-114' y='186.027'/>
+<use x='123.232' xlink:href='#g3-115' y='186.027'/>
+<use x='126.478' xlink:href='#g3-111' y='186.027'/>
+<use x='130.712' xlink:href='#g3-110' y='186.027'/>
+<use x='135.085' xlink:href='#g3-78' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' xlink:href='#g3-109' y='186.027'/>
+<use x='121.211' xlink:href='#g3-115' y='186.027'/>
+<use x='124.458' xlink:href='#g3-116' y='186.027'/>
+<use x='127.516' xlink:href='#g3-114' y='186.027'/>
+<use x='130.408' xlink:href='#g3-101' y='186.027'/>
+<use x='134.171' xlink:href='#g3-115' y='186.027'/>
+<use x='137.418' xlink:href='#g3-115' y='186.027'/>
+<use x='140.664' xlink:href='#g3-78' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='186.027'/>
+<use x='117.379' xlink:href='#g3-112' y='186.027'/>
+<use x='121.751' xlink:href='#g3-116' y='186.027'/>
+<use x='124.809' xlink:href='#g3-101' y='186.027'/>
+<use x='128.573' xlink:href='#g3-115' y='186.027'/>
+<use x='131.819' xlink:href='#g3-116' y='186.027'/>
+<use x='134.877' xlink:href='#g3-78' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' xlink:href='#g2-48' y='186.027'/>
+<use x='117.133' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
+<use x='114.487' xlink:href='#g2-48' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-53' y='186.027'/>
+<use x='121.25' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-53' y='186.027'/>
+<use x='121.25' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
+<use x='114.487' xlink:href='#g2-50' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-120' y='186.027'/>
+</g>
+<path clip-path='url(#clip1)' d='M82.148 143.961H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M88.945 206.586H92.18V143.961H88.945ZM147.613 206.586H150.852V143.961H147.613ZM206.281 206.586H209.52V143.961H206.281ZM264.949 206.586H268.188V143.961H264.949ZM323.621 206.586H326.859V143.961H323.621ZM382.289 206.586H385.527V143.961H382.289Z' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M88.945 206.586H92.18V143.961H88.945ZM147.613 206.586H150.852V143.961H147.613ZM206.281 206.586H209.52V143.961H206.281ZM264.949 206.586H268.188V143.961H264.949ZM323.621 206.586H326.859V143.961H323.621ZM382.289 206.586H385.527V143.961H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M90.563 143.961V143.898' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M90.563 143.961V143.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M88.57 143.898H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M90.563 143.961V144.023' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M90.563 143.961V144.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M92.555 144.024H88.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M149.231 143.961V143.523' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M149.231 143.961V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M147.238 143.524H151.226' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M149.231 143.961V144.398' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M149.231 143.961V144.398' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M151.223 144.398H147.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M207.902 143.961V142.207' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M207.902 143.961V142.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M205.91 142.207H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M207.902 143.961V145.715' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M207.902 143.961V145.715' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M209.891 145.715H205.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M266.57 143.961V143.336' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M266.57 143.961V143.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M264.578 143.336H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M266.57 143.961V144.586' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M266.57 143.961V144.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M268.563 144.586H264.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M325.238 143.961V143.586' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M325.238 143.961V143.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M323.246 143.586H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M325.238 143.961V144.336' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M325.238 143.961V144.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M327.231 144.336H323.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M383.906 143.961V143.523' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M383.906 143.961V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M381.914 143.524H385.902' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M383.906 143.961V144.398' fill='#993333'/>
+<path clip-path='url(#clip1)' d='M383.906 143.961V144.398' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M385.898 144.398H381.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M94.176 206.586H97.41V142.519H94.176ZM152.844 206.586H156.082V140.203H152.844ZM211.512 206.586H214.75V148.344H211.512ZM270.18 206.586H273.418V121.418H270.18ZM328.852 206.586H332.09V135.07H328.852ZM387.52 206.586H390.758V81.34H387.52Z' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M94.176 206.586H97.41V142.519H94.176ZM152.844 206.586H156.082V140.203H152.844ZM211.512 206.586H214.75V148.344H211.512ZM270.18 206.586H273.418V121.418H270.18ZM328.852 206.586H332.09V135.07H328.852ZM387.52 206.586H390.758V81.34H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M95.793 142.519V142.519' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M93.801 142.52H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M95.793 142.519V142.519' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M93.801 142.52H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M154.461 140.203V139.203' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M154.461 140.203V139.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M152.469 139.203H156.457' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M154.461 140.203V141.207' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M154.461 140.203V141.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M156.453 141.207H152.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M213.133 148.344V148.031' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M213.133 148.344V148.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M211.141 148.032H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M213.133 148.344V148.656' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M213.133 148.344V148.656' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M215.121 148.656H211.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M271.801 121.418V121.23' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M271.801 121.418V121.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M269.809 121.23H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M271.801 121.418V121.605' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M271.801 121.418V121.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M273.793 121.606H269.808' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M330.469 135.07V134.254' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M330.469 135.07V134.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M328.477 134.254H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M330.469 135.07V135.883' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M330.469 135.07V135.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M332.461 135.883H328.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M389.137 81.34V81.34' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M387.145 81.34H391.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M389.137 81.34V81.34' fill='#8080bf'/>
+<path clip-path='url(#clip1)' d='M387.145 81.34H391.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M99.406 206.586H102.641V140.266H99.406ZM158.074 206.586H161.313V142.898H158.074ZM216.742 206.586H219.981V134.754H216.742ZM275.41 206.586H278.649V99.25H275.41ZM334.082 206.586H337.32V81.34H334.082ZM392.75 206.586H395.988V81.34H392.75Z' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M99.406 206.586H102.641V140.266H99.406ZM158.074 206.586H161.313V142.898H158.074ZM216.742 206.586H219.981V134.754H216.742ZM275.41 206.586H278.649V99.25H275.41ZM334.082 206.586H337.32V81.34H334.082ZM392.75 206.586H395.988V81.34H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M101.024 140.266V140.203' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M101.024 140.266V140.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M99.031 140.203H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M101.024 140.266V140.328' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M101.024 140.266V140.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M103.016 140.328H99.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M159.691 142.898V142.269' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M159.691 142.898V142.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M157.699 142.269H161.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M159.691 142.898V143.523' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M159.691 142.898V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M161.684 143.524H157.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M218.363 134.754V134.066' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M218.363 134.754V134.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M216.371 134.067H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M218.363 134.754V135.445' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M218.363 134.754V135.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M220.352 135.445H216.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M277.031 99.25V91.168' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M277.031 99.25V91.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M275.039 91.172H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M277.031 99.25V107.328' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M277.031 99.25V107.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M279.024 107.328H275.039' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M335.699 81.34V81.34' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M333.707 81.34H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M335.699 81.34V81.34' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M333.707 81.34H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M394.367 81.34V81.34' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M392.375 81.34H396.363' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M394.367 81.34V81.34' fill='#ffb733'/>
+<path clip-path='url(#clip1)' d='M392.375 81.34H396.363' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M104.637 206.586H107.871V124.859H104.637ZM163.305 206.586H166.543V141.207H163.305ZM221.973 206.586H225.211V118.035H221.973ZM280.641 206.586H283.879V121.043H280.641ZM339.313 206.586H342.551V133.066H339.313ZM397.981 206.586H401.219V89.039H397.981Z' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M104.637 206.586H107.871V124.859H104.637ZM163.305 206.586H166.543V141.207H163.305ZM221.973 206.586H225.211V118.035H221.973ZM280.641 206.586H283.879V121.043H280.641ZM339.313 206.586H342.551V133.066H339.313ZM397.981 206.586H401.219V89.039H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M106.254 124.859V124.797' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M106.254 124.859V124.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M104.261 124.796H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M106.254 124.859V124.922' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M106.254 124.859V124.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M108.246 124.922H104.261' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M164.922 141.207V140.894' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M164.922 141.207V140.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M162.929 140.895H166.917' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M164.922 141.207V141.519' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M164.922 141.207V141.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M166.914 141.52H162.929' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M223.594 118.035V117.973' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M223.594 118.035V117.973' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M221.601 117.973H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M223.594 118.035V118.098' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M223.594 118.035V118.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M225.582 118.098H221.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M282.262 121.043V120.539' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M282.262 121.043V120.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M280.269 120.539H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M282.262 121.043V121.543' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M282.262 121.043V121.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M284.254 121.543H280.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M340.93 133.066V132.812' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M340.93 133.066V132.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M338.937 132.812H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M340.93 133.066V133.316' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M340.93 133.066V133.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M342.922 133.316H338.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M399.598 89.039V88.539' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M399.598 89.039V88.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M397.605 88.539H401.593' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M399.598 89.039V89.543' fill='#bf80bf'/>
+<path clip-path='url(#clip1)' d='M399.598 89.039V89.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M401.59 89.543H397.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M109.867 206.586H113.102V142.332H109.867ZM168.535 206.586H171.774V143.086H168.535ZM227.203 206.586H230.442V132.125H227.203ZM285.871 206.586H289.109V139.641H285.871ZM344.543 206.586H347.781V81.34H344.543ZM403.211 206.586H406.449V100.187H403.211Z' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M109.867 206.586H113.102V142.332H109.867ZM168.535 206.586H171.774V143.086H168.535ZM227.203 206.586H230.442V132.125H227.203ZM285.871 206.586H289.109V139.641H285.871ZM344.543 206.586H347.781V81.34H344.543ZM403.211 206.586H406.449V100.187H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M111.484 142.332V142.269' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M111.484 142.332V142.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M109.492 142.269H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M111.484 142.332V142.394' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M111.484 142.332V142.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M113.477 142.395H109.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M170.152 143.086V142.644' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M170.152 143.086V142.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M168.16 142.644H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M170.152 143.086V143.523' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M170.152 143.086V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M172.145 143.524H168.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M228.824 132.125V131.312' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M228.824 132.125V131.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M226.832 131.312H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M228.824 132.125V132.941' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M228.824 132.125V132.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M230.813 132.941H226.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M287.492 139.641V138.387' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M287.492 139.641V138.387' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M285.5 138.387H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M287.492 139.641V140.894' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M287.492 139.641V140.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M289.485 140.895H285.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M346.16 81.34V81.34' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M344.168 81.34H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M346.16 81.34V81.34' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M344.168 81.34H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M404.828 100.187V99.562' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M404.828 100.187V99.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M402.836 99.562H406.824' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M404.828 100.187V100.812' fill='#dfbf9f'/>
+<path clip-path='url(#clip1)' d='M404.828 100.187V100.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M406.821 100.813H402.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M115.098 206.586H118.332V135.57H115.098ZM173.766 206.586H177.004V136.07H173.766ZM232.434 206.586H235.672V114.965H232.434ZM291.102 206.586H294.34V113.84H291.102ZM349.774 206.586H353.012V81.34H349.774ZM408.442 206.586H411.68V81.34H408.442Z' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M115.098 206.586H118.332V135.57H115.098ZM173.766 206.586H177.004V136.07H173.766ZM232.434 206.586H235.672V114.965H232.434ZM291.102 206.586H294.34V113.84H291.102ZM349.774 206.586H353.012V81.34H349.774ZM408.442 206.586H411.68V81.34H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M116.715 135.57V135.508' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M116.715 135.57V135.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M114.722 135.508H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M116.715 135.57V135.633' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M116.715 135.57V135.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M118.707 135.633H114.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M175.383 136.07V135.258' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M175.383 136.07V135.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M173.39 135.258H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M175.383 136.07V136.883' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M175.383 136.07V136.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M177.375 136.883H173.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M234.055 114.965V114.09' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M234.055 114.965V114.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M232.062 114.09H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M234.055 114.965V115.844' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M234.055 114.965V115.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M236.043 115.843H232.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M292.723 113.84V113.215' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M292.723 113.84V113.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M290.73 113.215H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M292.723 113.84V114.465' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M292.723 113.84V114.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M294.715 114.465H290.73' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M351.391 81.34V81.34' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M349.398 81.34H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M351.391 81.34V81.34' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M349.398 81.34H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M410.059 81.34V81.34' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M408.066 81.34H412.054' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M410.059 81.34V81.34' fill='#80bf80'/>
+<path clip-path='url(#clip1)' d='M408.066 81.34H412.054' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M120.328 206.586H123.563V135.633H120.328ZM178.996 206.586H182.234V81.34H178.996ZM237.664 206.586H240.902V138.387H237.664ZM296.332 206.586H299.57V81.34H296.332ZM355.004 206.586H358.238V81.34H355.004ZM413.672 206.586H416.91V81.34H413.672Z' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M120.328 206.586H123.563V135.633H120.328ZM178.996 206.586H182.234V81.34H178.996ZM237.664 206.586H240.902V138.387H237.664ZM296.332 206.586H299.57V81.34H296.332ZM355.004 206.586H358.238V81.34H355.004ZM413.672 206.586H416.91V81.34H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M121.945 135.633V135.57' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M121.945 135.633V135.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M119.953 135.571H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M121.945 135.633V135.695' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M121.945 135.633V135.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M123.938 135.695H119.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M180.613 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M178.621 81.34H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M180.613 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M178.621 81.34H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M239.285 138.387V136.195' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M239.285 138.387V136.195' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M237.293 136.195H241.278' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M239.285 138.387V140.578' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M239.285 138.387V140.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M241.274 140.578H237.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M297.953 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M295.961 81.34H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M297.953 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M295.961 81.34H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M356.621 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M354.629 81.34H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M356.621 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M354.629 81.34H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M415.289 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M413.297 81.34H417.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M415.289 81.34V81.34' fill='#bfbf80'/>
+<path clip-path='url(#clip1)' d='M413.297 81.34H417.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M125.559 206.586H128.793V139.266H125.559ZM184.227 206.586H187.465V135.695H184.227ZM242.895 206.586H246.133V137.824H242.895ZM301.563 206.586H304.801V97.433H301.563ZM360.234 206.586H363.469V81.34H360.234ZM418.902 206.586H422.141V81.34H418.902Z' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M125.559 206.586H128.793V139.266H125.559ZM184.227 206.586H187.465V135.695H184.227ZM242.895 206.586H246.133V137.824H242.895ZM301.563 206.586H304.801V97.433H301.563ZM360.234 206.586H363.469V81.34H360.234ZM418.902 206.586H422.141V81.34H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M127.176 139.266V139.203' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M127.176 139.266V139.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M125.183 139.203H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M127.176 139.266V139.328' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M127.176 139.266V139.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M129.168 139.328H125.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M185.844 135.695V135.258' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M185.844 135.695V135.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M183.851 135.258H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M185.844 135.695V136.133' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M185.844 135.695V136.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M187.836 136.133H183.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M244.516 137.824V137.012' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M244.516 137.824V137.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M242.523 137.012H246.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M244.516 137.824V138.637' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M244.516 137.824V138.637' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M246.504 138.637H242.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M303.184 97.433V95.617' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M303.184 97.433V95.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M301.191 95.617H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M303.184 97.433V99.25' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M303.184 97.433V99.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M305.176 99.25H301.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M361.852 81.34V81.34' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M359.859 81.34H363.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M361.852 81.34V81.34' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M359.859 81.34H363.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M420.52 81.34V81.34' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M418.527 81.34H422.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M420.52 81.34V81.34' fill='#339999'/>
+<path clip-path='url(#clip1)' d='M418.527 81.34H422.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M130.789 206.586H134.024V136.508H130.789ZM189.457 206.586H192.695V143.023H189.457ZM248.125 206.586H251.363V139.391H248.125ZM306.793 206.586H310.031V134.191H306.793ZM365.465 206.586H368.699V81.34H365.465ZM424.133 206.586H427.371V85.348H424.133Z' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M130.789 206.586H134.024V136.508H130.789ZM189.457 206.586H192.695V143.023H189.457ZM248.125 206.586H251.363V139.391H248.125ZM306.793 206.586H310.031V134.191H306.793ZM365.465 206.586H368.699V81.34H365.465ZM424.133 206.586H427.371V85.348H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M132.406 136.508V136.445' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M132.406 136.508V136.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M130.414 136.445H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M132.406 136.508V136.57' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M132.406 136.508V136.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M134.399 136.571H130.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M191.074 143.023V142.582' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M191.074 143.023V142.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M189.082 142.582H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M191.074 143.023V143.461' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M191.074 143.023V143.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M193.067 143.461H189.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M249.746 139.391V136.383' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M249.746 139.391V136.383' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M247.754 136.383H251.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M249.746 139.391V142.394' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M249.746 139.391V142.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M251.735 142.395H247.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M308.414 134.191V131.875' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M308.414 134.191V131.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M306.422 131.875H310.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M308.414 134.191V136.508' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M308.414 134.191V136.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M310.407 136.508H306.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M367.082 81.34V81.34' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M365.09 81.34H369.075' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M367.082 81.34V81.34' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M365.09 81.34H369.075' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M425.75 85.348V72.633' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M425.75 85.348V72.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M423.758 72.633H427.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M425.75 85.348V98.058' fill='#bf8080'/>
+<path clip-path='url(#clip1)' d='M425.75 85.348V98.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M427.743 98.059H423.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -93.83 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.161 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.508 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.177 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.846 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.515 252.423)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -88.6 250.983)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-50' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.93 248.666)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-54' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.739 256.807)'>
+<use x='114.487' xlink:href='#g2-48' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-57' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.408 229.879)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-51' y='186.027'/>
+<use x='121.25' xlink:href='#g2-54' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.077 243.531)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-52' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.746 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-53' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-56' y='186.027'/>
+<use x='126.877' xlink:href='#g2-50' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.369 248.729)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-54' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.7 251.359)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-50' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.969 243.218)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-53' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.638 207.711)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-55' y='186.027'/>
+<use x='121.25' xlink:href='#g2-49' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.307 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-51' y='186.027'/>
+<use x='126.877' xlink:href='#g2-54' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.976 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-57' y='186.027'/>
+<use x='126.877' xlink:href='#g2-49' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.139 233.323)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-51' y='186.027'/>
+<use x='121.25' xlink:href='#g2-49' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.47 249.668)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-52' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.199 226.497)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-52' y='186.027'/>
+<use x='121.25' xlink:href='#g2-49' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.868 229.503)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-51' y='186.027'/>
+<use x='121.25' xlink:href='#g2-55' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.537 241.527)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-55' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.206 197.503)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-56' y='186.027'/>
+<use x='121.25' xlink:href='#g2-56' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -72.908 250.795)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.239 251.547)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-49' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.43 240.588)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-57' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.099 248.102)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-55' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.768 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-49' y='186.027'/>
+<use x='126.877' xlink:href='#g2-54' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.437 208.65)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-55' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -67.678 244.032)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.009 244.533)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.66 223.429)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-52' y='186.027'/>
+<use x='121.25' xlink:href='#g2-54' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.329 222.302)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-52' y='186.027'/>
+<use x='121.25' xlink:href='#g2-56' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.998 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-56' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-52' y='186.027'/>
+<use x='126.877' xlink:href='#g2-50' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.667 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-57' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-57' y='186.027'/>
+<use x='126.877' xlink:href='#g2-51' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.447 244.095)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.778 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-51' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-54' y='186.027'/>
+<use x='126.877' xlink:href='#g2-51' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.891 246.85)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-57' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.56 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-51' y='186.027'/>
+<use x='125.406' xlink:href='#g2-46' y='186.027'/>
+<use x='126.877' xlink:href='#g2-57' y='186.027'/>
+<use x='129.523' xlink:href='#g2-57' y='186.027'/>
+<use x='132.169' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.229 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-49' y='186.027'/>
+<use x='122.76' xlink:href='#g2-56' y='186.027'/>
+<use x='125.406' xlink:href='#g2-46' y='186.027'/>
+<use x='126.877' xlink:href='#g2-53' y='186.027'/>
+<use x='129.523' xlink:href='#g2-52' y='186.027'/>
+<use x='132.169' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.898 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-51' y='186.027'/>
+<use x='122.76' xlink:href='#g2-52' y='186.027'/>
+<use x='125.406' xlink:href='#g2-46' y='186.027'/>
+<use x='126.877' xlink:href='#g2-52' y='186.027'/>
+<use x='129.523' xlink:href='#g2-53' y='186.027'/>
+<use x='132.169' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.217 247.727)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-56' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.452 244.157)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-51' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.121 246.286)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-48' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.79 205.895)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-55' y='186.027'/>
+<use x='121.25' xlink:href='#g2-52' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.459 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-52' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-51' y='186.027'/>
+<use x='126.877' xlink:href='#g2-51' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 236.128 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-49' y='186.027'/>
+<use x='126.877' xlink:href='#g2-50' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -51.986 244.971)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-50' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.683 251.484)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-50' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 65.352 247.852)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-48' y='186.027'/>
+<use x='121.25' xlink:href='#g2-55' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 124.021 242.654)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-49' y='186.027'/>
+<use x='121.25' xlink:href='#g2-54' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.69 189.8)'>
+<use x='109.598' xlink:href='#g4-1' y='186.027'/>
+<use x='113.103' xlink:href='#g4-1' y='186.027'/>
+<use x='116.608' xlink:href='#g4-1' y='186.027'/>
+<use x='120.114' xlink:href='#g2-50' y='186.027'/>
+<use x='122.76' xlink:href='#g2-46' y='186.027'/>
+<use x='124.23' xlink:href='#g2-50' y='186.027'/>
+<use x='126.877' xlink:href='#g2-55' y='186.027'/>
+<use x='129.523' xlink:href='#g2-120' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 241.359 193.808)'>
+<use x='114.487' xlink:href='#g2-49' y='186.027'/>
+<use x='117.133' xlink:href='#g2-46' y='186.027'/>
+<use x='118.603' xlink:href='#g2-57' y='186.027'/>
+<use x='121.25' xlink:href='#g2-52' y='186.027'/>
+</g>
+<g transform='matrix(0 -1 1 0 -126.667 313.708)'>
+<use x='114.487' xlink:href='#g1-82' y='186.027'/>
+<use x='120.457' xlink:href='#g1-101' y='186.027'/>
+<use x='124.553' xlink:href='#g1-108' y='186.027'/>
+<use x='126.753' xlink:href='#g1-97' y='186.027'/>
+<use x='131.181' xlink:href='#g1-116' y='186.027'/>
+<use x='134.509' xlink:href='#g1-105' y='186.027'/>
+<use x='136.709' xlink:href='#g1-118' y='186.027'/>
+<use x='140.957' xlink:href='#g1-101' y='186.027'/>
+<use x='148.124' xlink:href='#g1-116' y='186.027'/>
+<use x='151.452' xlink:href='#g1-105' y='186.027'/>
+<use x='153.652' xlink:href='#g1-109' y='186.027'/>
+<use x='160.972' xlink:href='#g1-101' y='186.027'/>
+<use x='168.139' xlink:href='#g3-40' y='186.027'/>
+<use x='171.432' xlink:href='#g3-108' y='186.027'/>
+<use x='173.453' xlink:href='#g3-111' y='186.027'/>
+<use x='177.452' xlink:href='#g3-119' y='186.027'/>
+<use x='183' xlink:href='#g3-101' y='186.027'/>
+<use x='186.764' xlink:href='#g3-114' y='186.027'/>
+<use x='192.479' xlink:href='#g3-105' y='186.027'/>
+<use x='194.499' xlink:href='#g3-115' y='186.027'/>
+<use x='200.568' xlink:href='#g3-98' y='186.027'/>
+<use x='205.176' xlink:href='#g3-101' y='186.027'/>
+<use x='208.94' xlink:href='#g3-116' y='186.027'/>
+<use x='211.998' xlink:href='#g3-116' y='186.027'/>
+<use x='215.056' xlink:href='#g3-101' y='186.027'/>
+<use x='218.819' xlink:href='#g3-114' y='186.027'/>
+<use x='221.711' xlink:href='#g3-41' y='186.027'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg b/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg
new file mode 100644 (file)
index 0000000..2d853ed
--- /dev/null
@@ -0,0 +1,1185 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='258.383pt' version='1.1' viewBox='106.736 54.996 381.623 258.383' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip2'>
+<path d='M135.949 251.93H487.961V84.164H135.949Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-45' transform='scale(1.143)' xlink:href='#g0-45'/>
+<use id='g3-49' transform='scale(1.143)' xlink:href='#g0-49'/>
+<use id='g3-54' transform='scale(1.143)' xlink:href='#g0-54'/>
+<use id='g3-56' transform='scale(1.143)' xlink:href='#g0-56'/>
+<use id='g3-58' transform='scale(1.143)' xlink:href='#g0-58'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-103' transform='scale(1.143)' xlink:href='#g0-103'/>
+<use id='g3-104' transform='scale(1.143)' xlink:href='#g0-104'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-106' transform='scale(1.143)' xlink:href='#g0-106'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<use id='g3-120' transform='scale(1.143)' xlink:href='#g0-120'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-44' transform='scale(0.714)' xlink:href='#g0-44'/>
+<use id='g2-45' transform='scale(0.714)' xlink:href='#g0-45'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-64' transform='scale(0.714)' xlink:href='#g0-64'/>
+<use id='g2-67' transform='scale(0.714)' xlink:href='#g0-67'/>
+<use id='g2-71' transform='scale(0.714)' xlink:href='#g0-71'/>
+<use id='g2-73' transform='scale(0.714)' xlink:href='#g0-73'/>
+<use id='g2-85' transform='scale(0.714)' xlink:href='#g0-85'/>
+<use id='g2-88' transform='scale(0.714)' xlink:href='#g0-88'/>
+<use id='g2-97' transform='scale(0.714)' xlink:href='#g0-97'/>
+<use id='g2-98' transform='scale(0.714)' xlink:href='#g0-98'/>
+<use id='g2-99' transform='scale(0.714)' xlink:href='#g0-99'/>
+<use id='g2-100' transform='scale(0.714)' xlink:href='#g0-100'/>
+<use id='g2-101' transform='scale(0.714)' xlink:href='#g0-101'/>
+<use id='g2-103' transform='scale(0.714)' xlink:href='#g0-103'/>
+<use id='g2-104' transform='scale(0.714)' xlink:href='#g0-104'/>
+<use id='g2-108' transform='scale(0.714)' xlink:href='#g0-108'/>
+<use id='g2-109' transform='scale(0.714)' xlink:href='#g0-109'/>
+<use id='g2-110' transform='scale(0.714)' xlink:href='#g0-110'/>
+<use id='g2-111' transform='scale(0.714)' xlink:href='#g0-111'/>
+<use id='g2-112' transform='scale(0.714)' xlink:href='#g0-112'/>
+<use id='g2-114' transform='scale(0.714)' xlink:href='#g0-114'/>
+<use id='g2-115' transform='scale(0.714)' xlink:href='#g0-115'/>
+<use id='g2-116' transform='scale(0.714)' xlink:href='#g0-116'/>
+<use id='g2-117' transform='scale(0.714)' xlink:href='#g0-117'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<use id='g2-122' transform='scale(0.714)' xlink:href='#g0-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.007V-0.628H0.711V0H0.907L0.704 0.893H1.018L1.339 -0.007Z' id='g0-44'/>
+<path d='M2.05 -1.332V-1.771H0.084V-1.332H2.05Z' id='g0-45'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.339 -3.096H0.711V-2.469H1.339V-3.096ZM0.711 -0.628V0H1.339V-0.628H0.711Z' id='g0-58'/>
+<path d='M4.142 -0.614C4.038 -0.614 4.024 -0.614 3.968 -0.586C3.626 -0.467 3.271 -0.391 2.901 -0.391C1.778 -0.391 0.976 -1.339 0.976 -2.42C0.976 -3.592 1.883 -4.449 2.859 -4.449C3.055 -4.449 3.515 -4.4 3.745 -3.843C3.55 -3.954 3.333 -4.003 3.152 -4.003C2.406 -4.003 1.778 -3.306 1.778 -2.42C1.778 -1.513 2.427 -0.837 3.145 -0.837C3.689 -0.837 4.519 -1.276 4.519 -2.518C4.519 -3.222 4.47 -4.91 2.866 -4.91C1.541 -4.91 0.411 -3.815 0.411 -2.42C0.411 -1.039 1.527 0.07 2.873 0.07C3.515 0.07 4.115 -0.195 4.519 -0.614H4.142ZM3.152 -1.297C2.72 -1.297 2.343 -1.778 2.343 -2.42C2.343 -3.082 2.734 -3.543 3.145 -3.543C3.578 -3.543 3.954 -3.062 3.954 -2.42C3.954 -1.757 3.564 -1.297 3.152 -1.297Z' id='g0-64'/>
+<path d='M4.317 -0.851C3.829 -0.551 3.605 -0.418 2.908 -0.418C1.827 -0.418 1.172 -1.43 1.172 -2.434C1.172 -3.466 1.89 -4.435 2.908 -4.435C3.368 -4.435 3.843 -4.289 4.163 -4.045L4.275 -4.679C3.787 -4.861 3.396 -4.917 2.887 -4.917C1.506 -4.917 0.474 -3.773 0.474 -2.427C0.474 -0.99 1.569 0.07 2.929 0.07C3.612 0.07 3.898 -0.07 4.359 -0.321L4.317 -0.851Z' id='g0-67'/>
+<path d='M4.442 -2.085H2.88V-1.625H3.829V-0.558C3.522 -0.481 3.222 -0.418 2.908 -0.418C1.834 -0.418 1.172 -1.43 1.172 -2.427C1.172 -3.382 1.82 -4.435 2.873 -4.435C3.515 -4.435 3.919 -4.24 4.268 -3.947L4.38 -4.582C3.898 -4.812 3.473 -4.924 2.943 -4.924C1.534 -4.924 0.474 -3.822 0.474 -2.427C0.474 -1.067 1.527 0.07 2.901 0.07C3.403 0.07 3.996 -0.042 4.442 -0.272V-2.085Z' id='g0-71'/>
+<path d='M1.381 -4.84H0.676V0H1.381V-4.84Z' id='g0-73'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M4.4 -4.84H3.794V-1.625C3.794 -0.69 3.166 -0.265 2.566 -0.265S1.381 -0.697 1.381 -1.618V-4.84H0.676V-1.632C0.676 -0.607 1.555 0.146 2.559 0.146C3.557 0.146 4.4 -0.614 4.4 -1.632V-4.84Z' id='g0-85'/>
+<path d='M2.755 -2.552L4.519 -4.84H3.759L2.413 -3.055L1.039 -4.84H0.209L2.071 -2.552L0.105 0H0.865L2.413 -2.099L3.996 0H4.826L2.755 -2.552Z' id='g0-88'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M3.508 -3.166C3.354 -3.166 2.887 -3.159 2.357 -2.957L2.343 -2.95C2.092 -3.117 1.848 -3.166 1.646 -3.166C0.962 -3.166 0.453 -2.629 0.453 -2.029C0.453 -1.785 0.537 -1.534 0.697 -1.339C0.6 -1.22 0.495 -1.025 0.495 -0.76C0.495 -0.488 0.607 -0.314 0.669 -0.23C0.286 -0.007 0.209 0.314 0.209 0.481C0.209 1.011 0.941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 0.481C3.487 -0.502 2.267 -0.502 1.967 -0.502H1.318C1.206 -0.502 0.907 -0.502 0.907 -0.865C0.907 -1.004 0.955 -1.074 0.962 -1.088C1.206 -0.934 1.451 -0.886 1.639 -0.886C2.322 -0.886 2.831 -1.423 2.831 -2.022C2.831 -2.246 2.769 -2.448 2.643 -2.636C2.615 -2.678 2.615 -2.685 2.615 -2.692C2.615 -2.72 3.034 -2.72 3.068 -2.72C3.075 -2.72 3.34 -2.72 3.592 -2.692L3.508 -3.166ZM1.646 -1.318C1.269 -1.318 0.99 -1.555 0.99 -2.022C0.99 -2.566 1.339 -2.734 1.639 -2.734C2.015 -2.734 2.294 -2.497 2.294 -2.029C2.294 -1.485 1.946 -1.318 1.646 -1.318ZM1.974 0.042C2.134 0.042 2.957 0.042 2.957 0.488C2.957 0.788 2.434 0.997 1.848 0.997S0.739 0.788 0.739 0.488C0.739 0.453 0.739 0.042 1.304 0.042H1.974Z' id='g0-103'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.625 -3.166 1.304 -2.817 1.165 -2.671V-4.84H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-104'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.381 -4.784H0.676V-4.08H1.381V-4.784ZM-0.453 1.186C-0.133 1.36 0.181 1.423 0.446 1.423C0.928 1.423 1.381 1.053 1.381 0.411V-3.096H0.795V0.46C0.795 0.586 0.795 0.697 0.649 0.816C0.488 0.934 0.293 0.934 0.23 0.934C-0.063 0.934 -0.244 0.802 -0.328 0.725L-0.453 1.186Z' id='g0-106'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M3.243 -3.096H2.636V-1.074C2.636 -0.516 2.162 -0.342 1.757 -0.342C1.241 -0.342 1.186 -0.481 1.186 -0.802V-3.096H0.579V-0.76C0.579 -0.139 0.851 0.07 1.339 0.07C1.625 0.07 2.239 0.014 2.657 -0.321V0H3.243V-3.096Z' id='g0-117'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+<path d='M2.957 -2.803V-3.096H0.307V-2.65H1.332C1.416 -2.65 1.499 -2.657 1.583 -2.657H2.127L0.209 -0.307V0H2.978V-0.467H1.897C1.813 -0.467 1.73 -0.46 1.646 -0.46H1.039L2.957 -2.803Z' id='g0-122'/>
+</defs>
+<g id='page2'>
+<path d='M194.617 260.785V251.93M253.285 260.785V251.93M311.953 260.785V251.93M370.625 260.785V251.93M429.293 260.785V251.93M194.617 75.308V84.164M253.285 75.308V84.164M311.953 75.308V84.164M370.625 75.308V84.164M429.293 75.308V84.164' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 256.18V251.93M223.953 256.18V251.93M282.621 256.18V251.93M341.289 256.18V251.93M399.957 256.18V251.93M458.629 256.18V251.93M165.281 79.91V84.164M223.953 79.91V84.164M282.621 79.91V84.164M341.289 79.91V84.164M399.957 79.91V84.164M458.629 79.91V84.164' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 251.93H140.199M135.949 218.375H140.199M135.949 184.824H140.199M135.949 151.269H140.199M135.949 117.719H140.199M135.949 84.164H140.199M487.961 251.93H483.711M487.961 218.375H483.711M487.961 184.824H483.711M487.961 151.269H483.711M487.961 117.719H483.711M487.961 84.164H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 251.93V84.164H487.961V251.93H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='191.334'/>
+<use x='172.353' xlink:href='#g3-108' y='191.334'/>
+<use x='174.373' xlink:href='#g3-108' y='191.334'/>
+<use x='176.393' xlink:href='#g3-111' y='191.334'/>
+<use x='180.863' xlink:href='#g3-99' y='191.334'/>
+<use x='184.627' xlink:href='#g3-45' y='191.334'/>
+<use x='187.449' xlink:href='#g3-116' y='191.334'/>
+<use x='190.507' xlink:href='#g3-101' y='191.334'/>
+<use x='194.271' xlink:href='#g3-115' y='191.334'/>
+<use x='197.517' xlink:href='#g3-116' y='191.334'/>
+<use x='200.575' xlink:href='#g3-49' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='191.334'/>
+<use x='172.353' xlink:href='#g3-108' y='191.334'/>
+<use x='174.373' xlink:href='#g3-108' y='191.334'/>
+<use x='176.393' xlink:href='#g3-111' y='191.334'/>
+<use x='180.863' xlink:href='#g3-99' y='191.334'/>
+<use x='184.627' xlink:href='#g3-45' y='191.334'/>
+<use x='187.449' xlink:href='#g3-116' y='191.334'/>
+<use x='190.507' xlink:href='#g3-101' y='191.334'/>
+<use x='194.271' xlink:href='#g3-115' y='191.334'/>
+<use x='197.517' xlink:href='#g3-116' y='191.334'/>
+<use x='200.575' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='191.334'/>
+<use x='171.531' xlink:href='#g3-104' y='191.334'/>
+<use x='175.904' xlink:href='#g3-54' y='191.334'/>
+<use x='180.138' xlink:href='#g3-98' y='191.334'/>
+<use x='184.746' xlink:href='#g3-101' y='191.334'/>
+<use x='188.509' xlink:href='#g3-110' y='191.334'/>
+<use x='192.882' xlink:href='#g3-99' y='191.334'/>
+<use x='196.646' xlink:href='#g3-104' y='191.334'/>
+<use x='201.018' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='191.334'/>
+<use x='171.531' xlink:href='#g3-104' y='191.334'/>
+<use x='175.904' xlink:href='#g3-56' y='191.334'/>
+<use x='180.138' xlink:href='#g3-98' y='191.334'/>
+<use x='184.746' xlink:href='#g3-101' y='191.334'/>
+<use x='188.509' xlink:href='#g3-110' y='191.334'/>
+<use x='192.882' xlink:href='#g3-99' y='191.334'/>
+<use x='196.646' xlink:href='#g3-104' y='191.334'/>
+<use x='201.018' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' xlink:href='#g3-120' y='191.334'/>
+<use x='172.187' xlink:href='#g3-109' y='191.334'/>
+<use x='178.912' xlink:href='#g3-97' y='191.334'/>
+<use x='182.98' xlink:href='#g3-108' y='191.334'/>
+<use x='185' xlink:href='#g3-108' y='191.334'/>
+<use x='187.02' xlink:href='#g3-111' y='191.334'/>
+<use x='191.49' xlink:href='#g3-99' y='191.334'/>
+<use x='195.254' xlink:href='#g3-45' y='191.334'/>
+<use x='198.076' xlink:href='#g3-116' y='191.334'/>
+<use x='201.134' xlink:href='#g3-101' y='191.334'/>
+<use x='204.898' xlink:href='#g3-115' y='191.334'/>
+<use x='208.144' xlink:href='#g3-116' y='191.334'/>
+<use x='211.202' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' xlink:href='#g3-99' y='191.334'/>
+<use x='172.049' xlink:href='#g3-97' y='191.334'/>
+<use x='176.117' xlink:href='#g3-99' y='191.334'/>
+<use x='179.88' xlink:href='#g3-104' y='191.334'/>
+<use x='184.253' xlink:href='#g3-101' y='191.334'/>
+<use x='188.017' xlink:href='#g3-45' y='191.334'/>
+<use x='190.839' xlink:href='#g3-115' y='191.334'/>
+<use x='194.086' xlink:href='#g3-99' y='191.334'/>
+<use x='197.849' xlink:href='#g3-114' y='191.334'/>
+<use x='200.741' xlink:href='#g3-97' y='191.334'/>
+<use x='204.81' xlink:href='#g3-116' y='191.334'/>
+<use x='207.868' xlink:href='#g3-99' y='191.334'/>
+<use x='211.631' xlink:href='#g3-104' y='191.334'/>
+<use x='216.004' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' xlink:href='#g2-48' y='191.334'/>
+<use x='170.931' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' xlink:href='#g2-48' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<path clip-path='url(#clip2)' d='M135.949 184.824H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M142.742 251.93H145.981V184.824H142.742ZM201.41 251.93H204.649V184.824H201.41ZM260.078 251.93H263.317V184.824H260.078ZM318.75 251.93H321.988V184.824H318.75ZM377.418 251.93H380.656V184.824H377.418ZM436.086 251.93H439.324V184.824H436.086Z' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M142.742 251.93H145.981V184.824H142.742ZM201.41 251.93H204.649V184.824H201.41ZM260.078 251.93H263.317V184.824H260.078ZM318.75 251.93H321.988V184.824H318.75ZM377.418 251.93H380.656V184.824H377.418ZM436.086 251.93H439.324V184.824H436.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M144.359 184.824V184.758' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M144.359 184.824V184.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M142.367 184.758H146.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M144.359 184.824V184.891' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M144.359 184.824V184.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M146.352 184.891H142.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M203.031 184.824V184.621' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M203.031 184.824V184.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M201.039 184.621H205.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M203.031 184.824V185.023' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M203.031 184.824V185.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M205.023 185.023H201.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M261.699 184.824V179.855' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M261.699 184.824V179.855' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M259.707 179.855H263.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M261.699 184.824V189.789' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M261.699 184.824V189.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M263.691 189.789H259.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M320.367 184.824V184.824' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M318.375 184.824H322.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M320.367 184.824V184.824' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M318.375 184.824H322.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M379.035 184.824V184.152' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M379.035 184.824V184.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M377.043 184.152H381.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M379.035 184.824V185.492' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M379.035 184.824V185.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M381.027 185.492H377.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M437.707 184.824V179.254' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M437.707 184.824V179.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M435.715 179.254H439.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M437.707 184.824V190.394' fill='#993333'/>
+<path clip-path='url(#clip2)' d='M437.707 184.824V190.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M439.699 190.395H435.711' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M147.973 251.93H151.211V184.621H147.973ZM206.641 251.93H209.879V163.75H206.641ZM265.309 251.93H268.547V84.164H265.309ZM323.981 251.93H327.219V84.164H323.981ZM382.649 251.93H385.887V84.164H382.649ZM441.317 251.93H444.555V84.164H441.317Z' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M147.973 251.93H151.211V184.621H147.973ZM206.641 251.93H209.879V163.75H206.641ZM265.309 251.93H268.547V84.164H265.309ZM323.981 251.93H327.219V84.164H323.981ZM382.649 251.93H385.887V84.164H382.649ZM441.317 251.93H444.555V84.164H441.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M149.59 184.621V184.555' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M149.59 184.621V184.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M147.598 184.555H151.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M149.59 184.621V184.687' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M149.59 184.621V184.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M151.582 184.688H147.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M208.262 163.75V162.41' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M208.262 163.75V162.41' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M206.27 162.411H210.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M208.262 163.75V165.094' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M208.262 163.75V165.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M210.253 165.094H206.265' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M266.93 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M264.938 84.164H268.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M266.93 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M264.938 84.164H268.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M325.598 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M323.606 84.164H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M325.598 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M323.606 84.164H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M384.266 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M382.274 84.164H386.262' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M384.266 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M382.274 84.164H386.262' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M442.938 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M440.946 84.164H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M442.938 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip2)' d='M440.946 84.164H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M153.203 251.93H156.442V178.312H153.203ZM211.871 251.93H215.11V178.984H211.871ZM270.539 251.93H273.777V131.875H270.539ZM329.211 251.93H332.449V124.832H329.211ZM387.879 251.93H391.117V84.164H387.879ZM446.547 251.93H449.785V84.164H446.547Z' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M153.203 251.93H156.442V178.312H153.203ZM211.871 251.93H215.11V178.984H211.871ZM270.539 251.93H273.777V131.875H270.539ZM329.211 251.93H332.449V124.832H329.211ZM387.879 251.93H391.117V84.164H387.879ZM446.547 251.93H449.785V84.164H446.547Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M154.82 178.312V178.312' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M152.828 178.313H156.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M154.82 178.312V178.312' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M152.828 178.313H156.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M213.492 178.984V178.918' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M213.492 178.984V178.918' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M211.5 178.918H215.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M213.492 178.984V179.051' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M213.492 178.984V179.051' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M215.484 179.051H211.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M272.16 131.875V126.91' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M272.16 131.875V126.91' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M270.168 126.91H274.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M272.16 131.875V136.844' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M272.16 131.875V136.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M274.152 136.844H270.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M330.828 124.832V121.945' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M330.828 124.832V121.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M328.836 121.946H332.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M330.828 124.832V127.715' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M330.828 124.832V127.715' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M332.82 127.715H328.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M389.496 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M387.504 84.164H391.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M389.496 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M387.504 84.164H391.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M448.168 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M446.176 84.164H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M448.168 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip2)' d='M446.176 84.164H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M158.434 251.93H161.672V164.422H158.434ZM217.102 251.93H220.34V166.57H217.102ZM275.77 251.93H279.008V84.164H275.77ZM334.442 251.93H337.68V97.383H334.442ZM393.109 251.93H396.348V130.535H393.109ZM451.777 251.93H455.016V184.824H451.777Z' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M158.434 251.93H161.672V164.422H158.434ZM217.102 251.93H220.34V166.57H217.102ZM275.77 251.93H279.008V84.164H275.77ZM334.442 251.93H337.68V97.383H334.442ZM393.109 251.93H396.348V130.535H393.109ZM451.777 251.93H455.016V184.824H451.777Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M160.051 164.422V164.355' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M160.051 164.422V164.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M158.058 164.356H162.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M160.051 164.422V164.488' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M160.051 164.422V164.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M162.043 164.488H158.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M218.723 166.57V166.57' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M216.73 166.57H220.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M218.723 166.57V166.57' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M216.73 166.57H220.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M277.391 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M275.398 84.164H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M277.391 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M275.398 84.164H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M336.059 97.383V93.558' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M336.059 97.383V93.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M334.066 93.559H338.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M336.059 97.383V101.207' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M336.059 97.383V101.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M338.05 101.207H334.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M394.727 130.535V129.996' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M394.727 130.535V129.996' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M392.734 129.996H396.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M394.727 130.535V131.07' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M394.727 130.535V131.07' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M396.718 131.07H392.734' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M453.399 184.824V179.254' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M453.399 184.824V179.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M451.406 179.254H455.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M453.399 184.824V190.394' fill='#bf80bf'/>
+<path clip-path='url(#clip2)' d='M453.399 184.824V190.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M455.39 190.395H451.402' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M163.664 251.93H166.903V178.449H163.664ZM222.332 251.93H225.57V182.34H222.332ZM281 251.93H284.238V160.129H281ZM339.672 251.93H342.91V179.723H339.672ZM398.34 251.93H401.578V183.211H398.34ZM457.008 251.93H460.246V180.863H457.008Z' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M163.664 251.93H166.903V178.449H163.664ZM222.332 251.93H225.57V182.34H222.332ZM281 251.93H284.238V160.129H281ZM339.672 251.93H342.91V179.723H339.672ZM398.34 251.93H401.578V183.211H398.34ZM457.008 251.93H460.246V180.863H457.008Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M165.281 178.449V178.379' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M165.281 178.449V178.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M163.289 178.379H167.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M165.281 178.449V178.516' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M165.281 178.449V178.516' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M167.274 178.516H163.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M223.953 182.34V182.004' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M223.953 182.34V182.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M221.961 182.004H225.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M223.953 182.34V182.676' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M223.953 182.34V182.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M225.945 182.676H221.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M282.621 160.129V155.164' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M282.621 160.129V155.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M280.629 155.164H284.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M282.621 160.129V165.094' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M282.621 160.129V165.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M284.613 165.094H280.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M341.289 179.723V178.312' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M341.289 179.723V178.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M339.297 178.313H343.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M341.289 179.723V181.133' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M341.289 179.723V181.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M343.281 181.133H339.297' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M399.957 183.211V182.207' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M399.957 183.211V182.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M397.965 182.207H401.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M399.957 183.211V184.219' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M399.957 183.211V184.219' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M401.949 184.219H397.965' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M458.629 180.863V171.199' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M458.629 180.863V171.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M456.637 171.2H460.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M458.629 180.863V190.527' fill='#dfbf9f'/>
+<path clip-path='url(#clip2)' d='M458.629 180.863V190.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M460.621 190.527H456.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M168.895 251.93H172.133V175.496H168.895ZM227.563 251.93H230.801V84.164H227.563ZM286.231 251.93H289.469V84.164H286.231ZM344.902 251.93H348.141V84.164H344.902ZM403.57 251.93H406.809V84.164H403.57ZM462.238 251.93H465.477V84.164H462.238Z' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M168.895 251.93H172.133V175.496H168.895ZM227.563 251.93H230.801V84.164H227.563ZM286.231 251.93H289.469V84.164H286.231ZM344.902 251.93H348.141V84.164H344.902ZM403.57 251.93H406.809V84.164H403.57ZM462.238 251.93H465.477V84.164H462.238Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M170.512 175.496V175.43' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M170.512 175.496V175.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M168.519 175.429H172.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M170.512 175.496V175.562' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M170.512 175.496V175.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M172.504 175.562H168.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M229.184 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M227.191 84.164H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M229.184 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M227.191 84.164H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M287.852 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M285.859 84.164H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M287.852 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M285.859 84.164H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M346.52 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M344.527 84.164H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M346.52 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M344.527 84.164H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M405.188 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M403.195 84.164H407.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M405.188 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M403.195 84.164H407.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M463.859 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M461.867 84.164H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M463.859 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip2)' d='M461.867 84.164H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M174.125 251.93H177.363V120.402H174.125ZM232.793 251.93H236.031V84.164H232.793ZM291.461 251.93H294.699V84.164H291.461ZM350.133 251.93H353.371V84.164H350.133ZM408.801 251.93H412.039V84.164H408.801ZM467.469 251.93H470.707V184.824H467.469Z' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M174.125 251.93H177.363V120.402H174.125ZM232.793 251.93H236.031V84.164H232.793ZM291.461 251.93H294.699V84.164H291.461ZM350.133 251.93H353.371V84.164H350.133ZM408.801 251.93H412.039V84.164H408.801ZM467.469 251.93H470.707V184.824H467.469Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M175.742 120.402V120.266' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M175.742 120.402V120.266' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M173.75 120.266H177.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M175.742 120.402V120.535' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M175.742 120.402V120.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M177.735 120.535H173.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M234.414 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M232.422 84.164H236.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M234.414 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M232.422 84.164H236.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M293.082 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M291.09 84.164H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M293.082 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M291.09 84.164H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M351.75 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M349.758 84.164H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M351.75 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M349.758 84.164H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M410.418 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M408.426 84.164H412.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M410.418 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M408.426 84.164H412.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M469.09 184.824V179.254' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M469.09 184.824V179.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M467.098 179.254H471.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M469.09 184.824V190.394' fill='#bfbf80'/>
+<path clip-path='url(#clip2)' d='M469.09 184.824V190.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M471.082 190.395H467.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M179.356 251.93H182.594V168.652H179.356ZM238.024 251.93H241.262V169.457H238.024ZM296.692 251.93H299.93V84.164H296.692ZM355.363 251.93H358.602V84.164H355.363ZM414.031 251.93H417.27V84.164H414.031ZM472.699 251.93H475.938V84.164H472.699Z' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M179.356 251.93H182.594V168.652H179.356ZM238.024 251.93H241.262V169.457H238.024ZM296.692 251.93H299.93V84.164H296.692ZM355.363 251.93H358.602V84.164H355.363ZM414.031 251.93H417.27V84.164H414.031ZM472.699 251.93H475.938V84.164H472.699Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M180.973 168.652V168.582' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M180.973 168.652V168.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M178.98 168.582H182.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M180.973 168.652V168.719' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M180.973 168.652V168.719' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M182.965 168.719H178.98' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M239.645 169.457V169.387' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M239.645 169.457V169.387' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M237.652 169.387H241.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M239.645 169.457V169.523' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M239.645 169.457V169.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M241.633 169.524H237.648' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M298.313 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M296.32 84.164H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M298.313 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M296.32 84.164H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M356.981 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M354.988 84.164H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M356.981 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M354.988 84.164H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M415.649 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M413.656 84.164H417.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M415.649 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M413.656 84.164H417.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M474.32 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M472.328 84.164H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M474.32 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip2)' d='M472.328 84.164H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M184.586 251.93H187.824V176.301H184.586ZM243.254 251.93H246.492V177.309H243.254ZM301.922 251.93H305.16V84.164H301.922ZM360.594 251.93H363.832V84.164H360.594ZM419.262 251.93H422.5V143.621H419.262ZM477.93 251.93H481.168V176.906H477.93Z' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M184.586 251.93H187.824V176.301H184.586ZM243.254 251.93H246.492V177.309H243.254ZM301.922 251.93H305.16V84.164H301.922ZM360.594 251.93H363.832V84.164H360.594ZM419.262 251.93H422.5V143.621H419.262ZM477.93 251.93H481.168V176.906H477.93Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M186.203 176.301V175.965' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M186.203 176.301V175.965' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M184.211 175.965H188.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M186.203 176.301V176.637' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M186.203 176.301V176.637' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M188.196 176.637H184.211' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M244.875 177.309V177.172' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M244.875 177.309V177.172' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M242.883 177.172H246.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M244.875 177.309V177.441' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M244.875 177.309V177.441' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M246.864 177.441H242.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M303.543 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M301.551 84.164H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M303.543 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M301.551 84.164H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M362.211 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M360.219 84.164H364.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M362.211 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M360.219 84.164H364.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M420.879 143.621V142.746' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M420.879 143.621V142.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M418.887 142.746H422.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M420.879 143.621V144.492' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M420.879 143.621V144.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M422.871 144.492H418.887' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M479.551 176.906V171.336' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M479.551 176.906V171.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M477.559 171.336H481.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M479.551 176.906V182.473' fill='#bf8080'/>
+<path clip-path='url(#clip2)' d='M479.551 176.906V182.473' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M481.543 182.472H477.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M420.539 312.98H487.762V278.973H420.539Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 255.575 118.327)'>
+<use x='168.285' xlink:href='#g2-99' y='167.424'/>
+<use x='170.637' xlink:href='#g2-53' y='167.424'/>
+<use x='173.284' xlink:href='#g2-45' y='167.424'/>
+<use x='175.048' xlink:href='#g2-49' y='167.424'/>
+<use x='177.694' xlink:href='#g2-56' y='167.424'/>
+<use x='180.341' xlink:href='#g2-120' y='167.424'/>
+<use x='182.779' xlink:href='#g2-108' y='167.424'/>
+<use x='184.042' xlink:href='#g2-97' y='167.424'/>
+<use x='186.438' xlink:href='#g2-114' y='167.424'/>
+<use x='188.245' xlink:href='#g2-103' y='167.424'/>
+<use x='190.891' xlink:href='#g2-101' y='167.424'/>
+<use x='193.244' xlink:href='#g2-44' y='167.424'/>
+<use x='196.478' xlink:href='#g2-49' y='167.424'/>
+<use x='199.124' xlink:href='#g2-52' y='167.424'/>
+<use x='201.771' xlink:href='#g2-52' y='167.424'/>
+<use x='204.417' xlink:href='#g2-71' y='167.424'/>
+<use x='207.946' xlink:href='#g2-98' y='167.424'/>
+<use x='168.285' xlink:href='#g2-55' y='173.401'/>
+<use x='170.931' xlink:href='#g2-50' y='173.401'/>
+<use x='175.342' xlink:href='#g2-112' y='173.401'/>
+<use x='177.928' xlink:href='#g2-114' y='173.401'/>
+<use x='179.735' xlink:href='#g2-111' y='173.401'/>
+<use x='182.529' xlink:href='#g2-99' y='173.401'/>
+<use x='186.645' xlink:href='#g2-73' y='173.401'/>
+<use x='188.115' xlink:href='#g2-110' y='173.401'/>
+<use x='190.848' xlink:href='#g2-116' y='173.401'/>
+<use x='192.759' xlink:href='#g2-101' y='173.401'/>
+<use x='195.112' xlink:href='#g2-108' y='173.401'/>
+<use x='198.139' xlink:href='#g2-88' y='173.401'/>
+<use x='201.667' xlink:href='#g2-101' y='173.401'/>
+<use x='204.019' xlink:href='#g2-111' y='173.401'/>
+<use x='206.666' xlink:href='#g2-110' y='173.401'/>
+<use x='211.163' xlink:href='#g2-64' y='173.401'/>
+<use x='214.691' xlink:href='#g2-51' y='173.401'/>
+<use x='217.338' xlink:href='#g2-71' y='173.401'/>
+<use x='220.866' xlink:href='#g2-104' y='173.401'/>
+<use x='223.599' xlink:href='#g2-122' y='173.401'/>
+<use x='168.285' xlink:href='#g2-85' y='179.379'/>
+<use x='171.917' xlink:href='#g2-98' y='179.379'/>
+<use x='174.65' xlink:href='#g2-117' y='179.379'/>
+<use x='177.383' xlink:href='#g2-110' y='179.379'/>
+<use x='180.116' xlink:href='#g2-116' y='179.379'/>
+<use x='182.027' xlink:href='#g2-117' y='179.379'/>
+<use x='186.524' xlink:href='#g2-49' y='179.379'/>
+<use x='189.17' xlink:href='#g2-56' y='179.379'/>
+<use x='191.817' xlink:href='#g2-46' y='179.379'/>
+<use x='193.287' xlink:href='#g2-48' y='179.379'/>
+<use x='195.933' xlink:href='#g2-52' y='179.379'/>
+<use x='198.58' xlink:href='#g2-46' y='179.379'/>
+<use x='200.05' xlink:href='#g2-49' y='179.379'/>
+<use x='202.696' xlink:href='#g2-44' y='179.379'/>
+<use x='205.931' xlink:href='#g2-71' y='179.379'/>
+<use x='209.459' xlink:href='#g2-67' y='179.379'/>
+<use x='212.841' xlink:href='#g2-67' y='179.379'/>
+<use x='217.986' xlink:href='#g2-55' y='179.379'/>
+<use x='220.633' xlink:href='#g2-46' y='179.379'/>
+<use x='222.103' xlink:href='#g2-52' y='179.379'/>
+<use x='224.749' xlink:href='#g2-46' y='179.379'/>
+<use x='226.219' xlink:href='#g2-48' y='179.379'/>
+<use x='168.285' xlink:href='#g2-51' y='185.357'/>
+<use x='170.931' xlink:href='#g2-54' y='185.357'/>
+<use x='175.342' xlink:href='#g2-99' y='185.357'/>
+<use x='177.694' xlink:href='#g2-111' y='185.357'/>
+<use x='180.193' xlink:href='#g2-114' y='185.357'/>
+<use x='182.001' xlink:href='#g2-101' y='185.357'/>
+<use x='184.353' xlink:href='#g2-115' y='185.357'/>
+<use x='188.146' xlink:href='#g2-111' y='185.357'/>
+<use x='190.793' xlink:href='#g2-110' y='185.357'/>
+<use x='195.29' xlink:href='#g2-50' y='185.357'/>
+<use x='199.7' xlink:href='#g2-110' y='185.357'/>
+<use x='202.433' xlink:href='#g2-117' y='185.357'/>
+<use x='205.166' xlink:href='#g2-109' y='185.357'/>
+<use x='209.369' xlink:href='#g2-97' y='185.357'/>
+<use x='213.676' xlink:href='#g2-110' y='185.357'/>
+<use x='216.409' xlink:href='#g2-111' y='185.357'/>
+<use x='219.202' xlink:href='#g2-100' y='185.357'/>
+<use x='221.935' xlink:href='#g2-101' y='185.357'/>
+<use x='224.287' xlink:href='#g2-115' y='185.357'/>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-48' y='191.334'/>
+<use x='173.578' xlink:href='#g2-50' y='191.334'/>
+<use x='176.224' xlink:href='#g2-48' y='191.334'/>
+<use x='178.87' xlink:href='#g2-45' y='191.334'/>
+<use x='180.635' xlink:href='#g2-48' y='191.334'/>
+<use x='183.281' xlink:href='#g2-49' y='191.334'/>
+<use x='185.927' xlink:href='#g2-45' y='191.334'/>
+<use x='187.692' xlink:href='#g2-49' y='191.334'/>
+<use x='190.338' xlink:href='#g2-56' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -45.339 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 13.33 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 71.999 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.668 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 189.337 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 248.006 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.108 346.703)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.561 325.833)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-51' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 77.23 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-56' y='191.334'/>
+<use x='180.675' xlink:href='#g2-52' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.899 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-49' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-51' y='191.334'/>
+<use x='183.321' xlink:href='#g2-50' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.568 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-49' y='191.334'/>
+<use x='179.205' xlink:href='#g2-51' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-55' y='191.334'/>
+<use x='185.968' xlink:href='#g2-49' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 253.236 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-56' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-55' y='191.334'/>
+<use x='183.321' xlink:href='#g2-54' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -34.878 340.395)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.791 341.066)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.46 293.957)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-55' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 141.129 286.911)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-56' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.798 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-48' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-52' y='191.334'/>
+<use x='183.321' xlink:href='#g2-52' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 258.467 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-56' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-53' y='191.334'/>
+<use x='183.321' xlink:href='#g2-51' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.648 326.504)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-51' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 29.021 328.651)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.69 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-54' y='191.334'/>
+<use x='180.675' xlink:href='#g2-56' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.359 259.465)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-51' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 205.028 292.615)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-56' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 263.697 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.417 340.529)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 34.252 344.421)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.921 322.209)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-51' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.59 341.804)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-56' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 210.259 345.293)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-50' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 268.928 342.945)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.187 337.576)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.482 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-54' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-50' y='191.334'/>
+<use x='180.675' xlink:href='#g2-56' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 98.151 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-54' y='191.334'/>
+<use x='176.558' xlink:href='#g2-48' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-48' y='191.334'/>
+<use x='183.321' xlink:href='#g2-48' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.82 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-49' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-55' y='191.334'/>
+<use x='183.321' xlink:href='#g2-57' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.489 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-48' y='191.334'/>
+<use x='179.205' xlink:href='#g2-55' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-48' y='191.334'/>
+<use x='185.968' xlink:href='#g2-50' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 274.158 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-51' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-51' y='191.334'/>
+<use x='183.321' xlink:href='#g2-53' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -13.956 282.482)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-57' y='191.334'/>
+<use x='175.048' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.713 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-52' y='191.334'/>
+<use x='176.558' xlink:href='#g2-50' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-53' y='191.334'/>
+<use x='183.321' xlink:href='#g2-56' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.382 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-50' y='191.334'/>
+<use x='176.558' xlink:href='#g2-50' y='191.334'/>
+<use x='179.205' xlink:href='#g2-57' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-53' y='191.334'/>
+<use x='185.968' xlink:href='#g2-56' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 162.051 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-55' y='191.334'/>
+<use x='176.558' xlink:href='#g2-51' y='191.334'/>
+<use x='179.205' xlink:href='#g2-53' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-50' y='191.334'/>
+<use x='185.968' xlink:href='#g2-55' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.72 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-50' y='191.334'/>
+<use x='179.205' xlink:href='#g2-52' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-54' y='191.334'/>
+<use x='185.968' xlink:href='#g2-55' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 279.389 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -8.726 330.731)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.943 331.537)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.612 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-52' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-54' y='191.334'/>
+<use x='183.321' xlink:href='#g2-56' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 167.281 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-55' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-50' y='191.334'/>
+<use x='180.675' xlink:href='#g2-57' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.95 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-52' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-49' y='191.334'/>
+<use x='180.675' xlink:href='#g2-51' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 284.619 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-49' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-52' y='191.334'/>
+<use x='183.321' xlink:href='#g2-55' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.495 338.381)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 55.174 339.388)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.843 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-52' y='191.334'/>
+<use x='180.675' xlink:href='#g2-50' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.512 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-53' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-50' y='191.334'/>
+<use x='180.675' xlink:href='#g2-55' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 231.181 305.701)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-54' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 289.85 338.985)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-50' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.176 391.591)'>
+<use x='168.285' xlink:href='#g1-82' y='191.334'/>
+<use x='174.255' xlink:href='#g1-101' y='191.334'/>
+<use x='178.351' xlink:href='#g1-108' y='191.334'/>
+<use x='180.551' xlink:href='#g1-97' y='191.334'/>
+<use x='184.979' xlink:href='#g1-116' y='191.334'/>
+<use x='188.307' xlink:href='#g1-105' y='191.334'/>
+<use x='190.507' xlink:href='#g1-118' y='191.334'/>
+<use x='194.755' xlink:href='#g1-101' y='191.334'/>
+<use x='201.922' xlink:href='#g1-116' y='191.334'/>
+<use x='205.25' xlink:href='#g1-105' y='191.334'/>
+<use x='207.45' xlink:href='#g1-109' y='191.334'/>
+<use x='214.77' xlink:href='#g1-101' y='191.334'/>
+<use x='221.937' xlink:href='#g3-40' y='191.334'/>
+<use x='225.231' xlink:href='#g3-108' y='191.334'/>
+<use x='227.251' xlink:href='#g3-111' y='191.334'/>
+<use x='231.25' xlink:href='#g3-119' y='191.334'/>
+<use x='236.799' xlink:href='#g3-101' y='191.334'/>
+<use x='240.562' xlink:href='#g3-114' y='191.334'/>
+<use x='246.277' xlink:href='#g3-105' y='191.334'/>
+<use x='248.297' xlink:href='#g3-115' y='191.334'/>
+<use x='254.366' xlink:href='#g3-98' y='191.334'/>
+<use x='258.974' xlink:href='#g3-101' y='191.334'/>
+<use x='262.738' xlink:href='#g3-116' y='191.334'/>
+<use x='265.796' xlink:href='#g3-116' y='191.334'/>
+<use x='268.854' xlink:href='#g3-101' y='191.334'/>
+<use x='272.618' xlink:href='#g3-114' y='191.334'/>
+<use x='275.51' xlink:href='#g3-41' y='191.334'/>
+</g>
+<path d='M136.149 312.324H341.363V282.324H136.149Z' fill='#ffffff'/>
+<path d='M136.149 312.324H341.363V282.324H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' fill='#993333'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='195.372' xlink:href='#g3-120' y='178.327'/>
+<use x='199.274' xlink:href='#g3-109' y='178.327'/>
+<use x='205.999' xlink:href='#g3-105' y='178.327'/>
+<use x='208.019' xlink:href='#g3-58' y='178.327'/>
+<use x='210.371' xlink:href='#g0-57' y='178.327'/>
+<use x='214.076' xlink:href='#g0-57' y='178.327'/>
+</g>
+<path d='M184.145 292.816H187.133V284.844H184.145ZM190.121 292.816H193.109V286.836H190.121Z' fill='#8080bf'/>
+<path d='M184.145 292.816H187.133V284.844H184.145ZM190.121 292.816H193.109V286.836H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='239.382' xlink:href='#g3-116' y='178.327'/>
+<use x='242.44' xlink:href='#g3-99' y='178.327'/>
+<use x='246.204' xlink:href='#g3-58' y='178.327'/>
+<use x='248.556' xlink:href='#g0-53' y='178.327'/>
+<use x='252.261' xlink:href='#g0-55' y='178.327'/>
+</g>
+<path d='M227.356 292.816H230.344V284.844H227.356ZM233.332 292.816H236.32V286.836H233.332Z' fill='#ffb733'/>
+<path d='M227.356 292.816H230.344V284.844H227.356ZM233.332 292.816H236.32V286.836H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='281.863' xlink:href='#g3-106' y='178.327'/>
+<use x='284.119' xlink:href='#g3-101' y='178.327'/>
+<use x='287.882' xlink:href='#g3-58' y='178.327'/>
+<use x='290.235' xlink:href='#g0-53' y='178.327'/>
+<use x='293.94' xlink:href='#g0-56' y='178.327'/>
+</g>
+<path d='M269.106 292.816H272.094V284.844H269.106ZM275.086 292.816H278.074V286.836H275.086Z' fill='#bf80bf'/>
+<path d='M269.106 292.816H272.094V284.844H269.106ZM275.086 292.816H278.074V286.836H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='321.287' xlink:href='#g3-116' y='178.327'/>
+<use x='324.345' xlink:href='#g3-98' y='178.327'/>
+<use x='328.717' xlink:href='#g3-98' y='178.327'/>
+<use x='333.09' xlink:href='#g3-58' y='178.327'/>
+<use x='335.442' xlink:href='#g0-53' y='178.327'/>
+<use x='339.147' xlink:href='#g0-56' y='178.327'/>
+</g>
+<path d='M306.203 292.816H309.191V284.844H306.203ZM312.18 292.816H315.168V286.836H312.18Z' fill='#dfbf9f'/>
+<path d='M306.203 292.816H309.191V284.844H306.203ZM312.18 292.816H315.168V286.836H312.18Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='356.019' xlink:href='#g3-114' y='178.327'/>
+<use x='358.911' xlink:href='#g3-112' y='178.327'/>
+<use x='363.284' xlink:href='#g3-58' y='178.327'/>
+<use x='365.636' xlink:href='#g0-56' y='178.327'/>
+<use x='369.341' xlink:href='#g0-49' y='178.327'/>
+</g>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' fill='#80bf80'/>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='195.372' xlink:href='#g3-104' y='191.334'/>
+<use x='199.744' xlink:href='#g3-111' y='191.334'/>
+<use x='203.978' xlink:href='#g3-97' y='191.334'/>
+<use x='207.811' xlink:href='#g3-114' y='191.334'/>
+<use x='210.703' xlink:href='#g3-100' y='191.334'/>
+<use x='215.076' xlink:href='#g3-58' y='191.334'/>
+<use x='217.428' xlink:href='#g0-51' y='191.334'/>
+<use x='221.133' xlink:href='#g0-51' y='191.334'/>
+</g>
+<path d='M184.145 305.82H187.133V297.852H184.145ZM190.121 305.82H193.109V299.844H190.121Z' fill='#bfbf80'/>
+<path d='M184.145 305.82H187.133V297.852H184.145ZM190.121 305.82H193.109V299.844H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='239.382' xlink:href='#g3-109' y='191.334'/>
+<use x='246.107' xlink:href='#g3-101' y='191.334'/>
+<use x='249.871' xlink:href='#g3-115' y='191.334'/>
+<use x='253.117' xlink:href='#g3-104' y='191.334'/>
+<use x='257.489' xlink:href='#g3-58' y='191.334'/>
+<use x='259.842' xlink:href='#g0-50' y='191.334'/>
+<use x='263.547' xlink:href='#g0-56' y='191.334'/>
+</g>
+<path d='M227.356 305.82H230.344V297.852H227.356ZM233.332 305.82H236.32V299.844H233.332Z' fill='#339999'/>
+<path d='M227.356 305.82H230.344V297.852H227.356ZM233.332 305.82H236.32V299.844H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='281.863' xlink:href='#g3-103' y='191.334'/>
+<use x='286.097' xlink:href='#g3-108' y='191.334'/>
+<use x='288.118' xlink:href='#g3-105' y='191.334'/>
+<use x='290.138' xlink:href='#g3-98' y='191.334'/>
+<use x='294.746' xlink:href='#g3-99' y='191.334'/>
+<use x='298.509' xlink:href='#g3-58' y='191.334'/>
+<use x='300.862' xlink:href='#g0-52' y='191.334'/>
+<use x='304.567' xlink:href='#g0-55' y='191.334'/>
+</g>
+<path d='M269.106 305.82H272.094V297.852H269.106ZM275.086 305.82H278.074V299.844H275.086Z' fill='#bf8080'/>
+<path d='M269.106 305.82H272.094V297.852H269.106ZM275.086 305.82H278.074V299.844H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='321.287' xlink:href='#g3-115' y='191.334'/>
+<use x='324.533' xlink:href='#g3-109' y='191.334'/>
+<use x='331.258' xlink:href='#g3-105' y='191.334'/>
+<use x='333.278' xlink:href='#g3-58' y='191.334'/>
+<use x='335.63' xlink:href='#g0-54' y='191.334'/>
+<use x='339.335' xlink:href='#g0-55' y='191.334'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg b/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg
new file mode 100644 (file)
index 0000000..393bfad
--- /dev/null
@@ -0,0 +1,757 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='193.064pt' version='1.1' viewBox='52.938 51.67 381.624 193.064' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip7'>
+<path d='M82.148 228.594H434.164V60.828H82.148Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g1-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g1-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+</defs>
+<g id='page7'>
+<path d='M140.82 237.449V228.594M199.488 237.449V228.594M258.156 237.449V228.594M316.824 237.449V228.594M375.496 237.449V228.594M140.82 51.969V60.828M199.488 51.969V60.828M258.156 51.969V60.828M316.824 51.969V60.828M375.496 51.969V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 232.844V228.594M170.152 232.844V228.594M228.824 232.844V228.594M287.492 232.844V228.594M346.16 232.844V228.594M404.828 232.844V228.594M111.484 56.574V60.828M170.152 56.574V60.828M228.824 56.574V60.828M287.492 56.574V60.828M346.16 56.574V60.828M404.828 56.574V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 228.594H86.402M82.148 195.039H86.402M82.148 161.484H86.402M82.148 127.934H86.402M82.148 94.379H86.402M82.148 60.828H86.402M434.164 228.594H429.91M434.164 195.039H429.91M434.164 161.484H429.91M434.164 127.934H429.91M434.164 94.379H429.91M434.164 60.828H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 228.594V60.828H434.164V228.594H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' xlink:href='#g3-99' y='208.035'/>
+<use x='118.25' xlink:href='#g3-102' y='208.035'/>
+<use x='120.838' xlink:href='#g3-114' y='208.035'/>
+<use x='123.73' xlink:href='#g3-97' y='208.035'/>
+<use x='127.798' xlink:href='#g3-99' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='208.035'/>
+<use x='116.507' xlink:href='#g3-101' y='208.035'/>
+<use x='120.271' xlink:href='#g3-97' y='208.035'/>
+<use x='124.339' xlink:href='#g3-110' y='208.035'/>
+<use x='128.711' xlink:href='#g3-78' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='208.035'/>
+<use x='117.379' xlink:href='#g3-101' y='208.035'/>
+<use x='121.142' xlink:href='#g3-100' y='208.035'/>
+<use x='125.515' xlink:href='#g3-105' y='208.035'/>
+<use x='127.535' xlink:href='#g3-115' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='208.035'/>
+<use x='116.507' xlink:href='#g3-97' y='208.035'/>
+<use x='120.34' xlink:href='#g3-114' y='208.035'/>
+<use x='123.232' xlink:href='#g3-115' y='208.035'/>
+<use x='126.478' xlink:href='#g3-111' y='208.035'/>
+<use x='130.712' xlink:href='#g3-110' y='208.035'/>
+<use x='135.085' xlink:href='#g3-78' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' xlink:href='#g3-109' y='208.035'/>
+<use x='121.211' xlink:href='#g3-115' y='208.035'/>
+<use x='124.458' xlink:href='#g3-116' y='208.035'/>
+<use x='127.516' xlink:href='#g3-114' y='208.035'/>
+<use x='130.408' xlink:href='#g3-101' y='208.035'/>
+<use x='134.171' xlink:href='#g3-115' y='208.035'/>
+<use x='137.418' xlink:href='#g3-115' y='208.035'/>
+<use x='140.664' xlink:href='#g3-78' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='208.035'/>
+<use x='117.379' xlink:href='#g3-112' y='208.035'/>
+<use x='121.751' xlink:href='#g3-116' y='208.035'/>
+<use x='124.809' xlink:href='#g3-101' y='208.035'/>
+<use x='128.573' xlink:href='#g3-115' y='208.035'/>
+<use x='131.819' xlink:href='#g3-116' y='208.035'/>
+<use x='134.877' xlink:href='#g3-78' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-120' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -11.361)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-120' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -44.915)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-120' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.468)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-120' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -112.021)'>
+<use x='114.487' xlink:href='#g2-50' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-120' y='208.035'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -145.574)'>
+<use x='114.487' xlink:href='#g2-50' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-120' y='208.035'/>
+</g>
+<path clip-path='url(#clip7)' d='M82.148 161.484H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M88.945 228.594H92.18V161.484H88.945ZM147.613 228.594H150.852V161.484H147.613ZM206.281 228.594H209.52V161.484H206.281ZM264.949 228.594H268.188V161.484H264.949ZM323.621 228.594H326.859V161.484H323.621ZM382.289 228.594H385.527V161.484H382.289Z' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M88.945 228.594H92.18V161.484H88.945ZM147.613 228.594H150.852V161.484H147.613ZM206.281 228.594H209.52V161.484H206.281ZM264.949 228.594H268.188V161.484H264.949ZM323.621 228.594H326.859V161.484H323.621ZM382.289 228.594H385.527V161.484H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M90.563 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M88.57 161.484H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M90.563 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M88.57 161.484H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M149.231 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M147.238 161.484H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M149.231 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M147.238 161.484H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M207.902 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M205.906 161.484H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M207.902 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M205.906 161.484H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M266.57 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M264.578 161.484H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M266.57 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M264.578 161.484H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M325.238 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M323.246 161.484H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M325.238 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M323.246 161.484H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M383.906 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M381.914 161.484H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M383.906 161.484V161.484' fill='#ffffff'/>
+<path clip-path='url(#clip7)' d='M381.914 161.484H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M94.176 228.594H97.41V74.719H94.176ZM152.844 228.594H156.082V172.559H152.844ZM211.512 228.594H214.75V145.852H211.512ZM270.18 228.594H273.418V154.773H270.18ZM328.852 228.594H332.09V193.43H328.852ZM387.52 228.594H390.758V191.148H387.52Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M94.176 228.594H97.41V74.719H94.176ZM152.844 228.594H156.082V172.559H152.844ZM211.512 228.594H214.75V145.852H211.512ZM270.18 228.594H273.418V154.773H270.18ZM328.852 228.594H332.09V193.43H328.852ZM387.52 228.594H390.758V191.148H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M95.793 74.719V74.719' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M93.801 74.719H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M95.793 74.719V74.719' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M93.801 74.719H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M154.461 172.559V172.559' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M152.469 172.558H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M154.461 172.559V172.559' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M152.469 172.558H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M213.133 145.852V145.852' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M211.137 145.851H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M213.133 145.852V145.852' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M211.137 145.851H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M271.801 154.773V154.773' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M269.809 154.773H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M271.801 154.773V154.773' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M269.809 154.773H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M330.469 193.43V193.43' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M328.477 193.429H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M330.469 193.43V193.43' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M328.477 193.429H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M389.137 191.148V191.148' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M387.145 191.149H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M389.137 191.148V191.148' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M387.145 191.149H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M99.406 228.594H102.641V138.133H99.406ZM158.074 228.594H161.313V162.961H158.074ZM216.742 228.594H219.981V157.797H216.742ZM275.41 228.594H278.649V141.02H275.41ZM334.082 228.594H337.32V191.816H334.082ZM392.75 228.594H395.988V179.871H392.75Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M99.406 228.594H102.641V138.133H99.406ZM158.074 228.594H161.313V162.961H158.074ZM216.742 228.594H219.981V157.797H216.742ZM275.41 228.594H278.649V141.02H275.41ZM334.082 228.594H337.32V191.816H334.082ZM392.75 228.594H395.988V179.871H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M101.024 138.133V138.133' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M99.031 138.133H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M101.024 138.133V138.133' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M99.031 138.133H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M159.691 162.961V162.961' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M157.699 162.961H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M159.691 162.961V162.961' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M157.699 162.961H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M218.363 157.797V157.797' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M216.367 157.797H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M218.363 157.797V157.797' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M216.367 157.797H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M277.031 141.02V141.02' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M275.039 141.02H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M277.031 141.02V141.02' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M275.039 141.02H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M335.699 191.816V191.816' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M333.707 191.816H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M335.699 191.816V191.816' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M333.707 191.816H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M394.367 179.871V179.871' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M392.375 179.871H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M394.367 179.871V179.871' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M392.375 179.871H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M104.637 228.594H107.871V140.883H104.637ZM163.305 228.594H166.543V152.695H163.305ZM221.973 228.594H225.211V115.184H221.973ZM280.641 228.594H283.879V167.793H280.641ZM339.313 228.594H342.551V189.738H339.313ZM397.981 228.594H401.219V194.367H397.981Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M104.637 228.594H107.871V140.883H104.637ZM163.305 228.594H166.543V152.695H163.305ZM221.973 228.594H225.211V115.184H221.973ZM280.641 228.594H283.879V167.793H280.641ZM339.313 228.594H342.551V189.738H339.313ZM397.981 228.594H401.219V194.367H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M106.254 140.883V140.883' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M104.261 140.882H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M106.254 140.883V140.883' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M104.261 140.882H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M164.922 152.695V152.695' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M162.929 152.695H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M164.922 152.695V152.695' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M162.929 152.695H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M223.594 115.184V115.184' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M221.597 115.184H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M223.594 115.184V115.184' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M221.597 115.184H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M282.262 167.793V167.793' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M280.269 167.793H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M282.262 167.793V167.793' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M280.269 167.793H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M340.93 189.738V189.738' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M338.937 189.739H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M340.93 189.738V189.738' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M338.937 189.739H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M399.598 194.367V194.367' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M397.605 194.367H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M399.598 194.367V194.367' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M397.605 194.367H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M109.867 228.594H113.102V163.031H109.867ZM168.535 228.594H171.774V157.191H168.535ZM227.203 228.594H230.442V142.094H227.203ZM285.871 228.594H289.109V150.414H285.871ZM344.543 228.594H347.781V150.949H344.543ZM403.211 228.594H406.449V103.105H403.211Z' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M109.867 228.594H113.102V163.031H109.867ZM168.535 228.594H171.774V157.191H168.535ZM227.203 228.594H230.442V142.094H227.203ZM285.871 228.594H289.109V150.414H285.871ZM344.543 228.594H347.781V150.949H344.543ZM403.211 228.594H406.449V103.105H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M111.484 163.031V163.031' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M109.492 163.031H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M111.484 163.031V163.031' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M109.492 163.031H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M170.152 157.191V157.191' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M168.16 157.191H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M170.152 157.191V157.191' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M168.16 157.191H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M228.824 142.094V142.094' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M226.828 142.093H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M228.824 142.094V142.094' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M226.828 142.093H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M287.492 150.414V150.414' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M285.5 150.414H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M287.492 150.414V150.414' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M285.5 150.414H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M346.16 150.949V150.949' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M344.168 150.949H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M346.16 150.949V150.949' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M344.168 150.949H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M404.828 103.105V103.105' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M402.836 103.106H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M404.828 103.105V103.105' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M402.836 103.106H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M115.098 228.594H118.332V133.906H115.098ZM173.766 228.594H177.004V148.133H173.766ZM232.434 228.594H235.672V144.91H232.434ZM291.102 228.594H294.34V160.48H291.102ZM349.774 228.594H353.012V168.801H349.774ZM408.442 228.594H411.68V181.484H408.442Z' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M115.098 228.594H118.332V133.906H115.098ZM173.766 228.594H177.004V148.133H173.766ZM232.434 228.594H235.672V144.91H232.434ZM291.102 228.594H294.34V160.48H291.102ZM349.774 228.594H353.012V168.801H349.774ZM408.442 228.594H411.68V181.484H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M116.715 133.906V133.906' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M114.722 133.906H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M116.715 133.906V133.906' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M114.722 133.906H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M175.383 148.133V148.133' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M173.39 148.133H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M175.383 148.133V148.133' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M173.39 148.133H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M234.055 144.91V144.91' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M232.058 144.91H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M234.055 144.91V144.91' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M232.058 144.91H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M292.723 160.48V160.48' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M290.73 160.48H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M292.723 160.48V160.48' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M290.73 160.48H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M351.391 168.801V168.801' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M349.398 168.801H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M351.391 168.801V168.801' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M349.398 168.801H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M410.059 181.484V181.484' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M408.066 181.485H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M410.059 181.484V181.484' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M408.066 181.485H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M120.328 228.594H123.563V140.48H120.328ZM178.996 228.594H182.234V159.473H178.996ZM237.664 228.594H240.902V159.406H237.664ZM296.332 228.594H299.57V157.797H296.332ZM355.004 228.594H358.238V172.355H355.004ZM413.672 228.594H416.91V184.637H413.672Z' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M120.328 228.594H123.563V140.48H120.328ZM178.996 228.594H182.234V159.473H178.996ZM237.664 228.594H240.902V159.406H237.664ZM296.332 228.594H299.57V157.797H296.332ZM355.004 228.594H358.238V172.355H355.004ZM413.672 228.594H416.91V184.637H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M121.945 140.48V140.48' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M119.953 140.481H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M121.945 140.48V140.48' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M119.953 140.481H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M180.613 159.473V159.473' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M178.621 159.473H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M180.613 159.473V159.473' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M178.621 159.473H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M239.285 159.406V159.406' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M237.289 159.407H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M239.285 159.406V159.406' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M237.289 159.407H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M297.953 157.797V157.797' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M295.961 157.797H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M297.953 157.797V157.797' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M295.961 157.797H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M356.621 172.355V172.355' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M354.629 172.355H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M356.621 172.355V172.355' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M354.629 172.355H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M415.289 184.637V184.637' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M413.297 184.637H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M415.289 184.637V184.637' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M413.297 184.637H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M125.559 228.594H128.793V163.098H125.559ZM184.227 228.594H187.465V151.824H184.227ZM242.895 228.594H246.133V161.082H242.895ZM301.563 228.594H304.801V167.457H301.563ZM360.234 228.594H363.469V168.195H360.234ZM418.902 228.594H422.141V199.332H418.902Z' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M125.559 228.594H128.793V163.098H125.559ZM184.227 228.594H187.465V151.824H184.227ZM242.895 228.594H246.133V161.082H242.895ZM301.563 228.594H304.801V167.457H301.563ZM360.234 228.594H363.469V168.195H360.234ZM418.902 228.594H422.141V199.332H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M127.176 163.098V163.098' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M125.183 163.097H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M127.176 163.098V163.098' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M125.183 163.097H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M185.844 151.824V151.824' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M183.851 151.825H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M185.844 151.824V151.824' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M183.851 151.825H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M244.516 161.082V161.082' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M242.519 161.082H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M244.516 161.082V161.082' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M242.519 161.082H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M303.184 167.457V167.457' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M301.191 167.457H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M303.184 167.457V167.457' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M301.191 167.457H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M361.852 168.195V168.195' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M359.859 168.196H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M361.852 168.195V168.195' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M359.859 168.196H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M420.52 199.332V199.332' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M418.527 199.332H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M420.52 199.332V199.332' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M418.527 199.332H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M130.789 228.594H134.024V157.996H130.789ZM189.457 228.594H192.695V153.969H189.457ZM248.125 228.594H251.363V154.305H248.125ZM306.793 228.594H310.031V122.633H306.793ZM365.465 228.594H368.699V165.98H365.465ZM424.133 228.594H427.371V150.211H424.133Z' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M130.789 228.594H134.024V157.996H130.789ZM189.457 228.594H192.695V153.969H189.457ZM248.125 228.594H251.363V154.305H248.125ZM306.793 228.594H310.031V122.633H306.793ZM365.465 228.594H368.699V165.98H365.465ZM424.133 228.594H427.371V150.211H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M132.406 157.996V157.996' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M130.414 157.996H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M132.406 157.996V157.996' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M130.414 157.996H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M191.074 153.969V153.969' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M189.082 153.969H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M191.074 153.969V153.969' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M189.082 153.969H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M249.746 154.305V154.305' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M247.75 154.305H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M249.746 154.305V154.305' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M247.75 154.305H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M308.414 122.633V122.633' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M306.422 122.633H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M308.414 122.633V122.633' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M306.422 122.633H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M367.082 165.98V165.98' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M365.09 165.98H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M367.082 165.98V165.98' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M365.09 165.98H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M425.75 150.211V150.211' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M423.758 150.211H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M425.75 150.211V150.211' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M423.758 150.211H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -115.838 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.169 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.5 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.169 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.838 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.507 269.769)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -110.608 183.001)'>
+<use x='114.487' xlink:href='#g2-50' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-50' y='208.035'/>
+<use x='121.25' xlink:href='#g2-57' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -51.938 280.841)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-56' y='208.035'/>
+<use x='121.25' xlink:href='#g2-52' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.731 254.133)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-50' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 65.4 263.058)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 124.069 301.711)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-50' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.738 299.43)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-54' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -105.377 246.416)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-51' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -46.708 271.245)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-56' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 11.961 266.078)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 70.63 249.302)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-51' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 129.299 300.101)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 187.968 288.156)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-55' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -100.147 249.167)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-51' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -41.478 260.978)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 17.191 223.466)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-54' y='208.035'/>
+<use x='121.25' xlink:href='#g2-57' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 75.86 276.077)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 134.529 298.021)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-56' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 193.198 302.651)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -94.916 271.312)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-56' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -36.247 265.474)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-54' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 22.422 250.375)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-50' y='208.035'/>
+<use x='121.25' xlink:href='#g2-57' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 81.091 258.696)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-54' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 139.76 259.233)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-54' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 198.429 211.387)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-56' y='208.035'/>
+<use x='121.25' xlink:href='#g2-55' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -89.686 242.188)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-52' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -31.017 256.415)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-50' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 27.652 253.194)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-50' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.321 268.762)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-50' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 144.99 277.083)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-56' y='208.035'/>
+<use x='121.25' xlink:href='#g2-57' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 203.659 289.767)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-55' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -84.455 248.765)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-51' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.786 267.756)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 32.883 267.689)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 91.552 266.078)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.221 280.64)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-56' y='208.035'/>
+<use x='121.25' xlink:href='#g2-52' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 208.89 292.921)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-54' y='208.035'/>
+<use x='121.25' xlink:href='#g2-54' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -79.225 271.379)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-56' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -20.556 260.106)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-52' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 38.113 269.366)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 96.782 275.741)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 155.451 276.48)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-48' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 214.12 307.617)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-52' y='208.035'/>
+<use x='121.25' xlink:href='#g2-52' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -73.994 266.279)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-48' y='208.035'/>
+<use x='121.25' xlink:href='#g2-53' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -15.325 262.253)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 43.344 262.589)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-49' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 102.013 230.914)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-53' y='208.035'/>
+<use x='121.25' xlink:href='#g2-56' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 160.682 274.265)'>
+<use x='114.487' xlink:href='#g2-48' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-57' y='208.035'/>
+<use x='121.25' xlink:href='#g2-51' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 219.351 258.495)'>
+<use x='114.487' xlink:href='#g2-49' y='208.035'/>
+<use x='117.133' xlink:href='#g2-46' y='208.035'/>
+<use x='118.603' xlink:href='#g2-49' y='208.035'/>
+<use x='121.25' xlink:href='#g2-55' y='208.035'/>
+</g>
+<g transform='matrix(0 -1 1 0 -148.675 311.091)'>
+<use x='114.487' xlink:href='#g1-82' y='208.035'/>
+<use x='120.457' xlink:href='#g1-101' y='208.035'/>
+<use x='124.553' xlink:href='#g1-108' y='208.035'/>
+<use x='126.753' xlink:href='#g1-97' y='208.035'/>
+<use x='131.181' xlink:href='#g1-116' y='208.035'/>
+<use x='134.509' xlink:href='#g1-105' y='208.035'/>
+<use x='136.709' xlink:href='#g1-118' y='208.035'/>
+<use x='140.957' xlink:href='#g1-101' y='208.035'/>
+<use x='148.124' xlink:href='#g1-114' y='208.035'/>
+<use x='151.272' xlink:href='#g1-115' y='208.035'/>
+<use x='154.805' xlink:href='#g1-115' y='208.035'/>
+<use x='161.409' xlink:href='#g3-40' y='208.035'/>
+<use x='164.702' xlink:href='#g3-108' y='208.035'/>
+<use x='166.722' xlink:href='#g3-111' y='208.035'/>
+<use x='170.721' xlink:href='#g3-119' y='208.035'/>
+<use x='176.27' xlink:href='#g3-101' y='208.035'/>
+<use x='180.034' xlink:href='#g3-114' y='208.035'/>
+<use x='185.749' xlink:href='#g3-105' y='208.035'/>
+<use x='187.769' xlink:href='#g3-115' y='208.035'/>
+<use x='193.838' xlink:href='#g3-98' y='208.035'/>
+<use x='198.446' xlink:href='#g3-101' y='208.035'/>
+<use x='202.209' xlink:href='#g3-116' y='208.035'/>
+<use x='205.267' xlink:href='#g3-116' y='208.035'/>
+<use x='208.325' xlink:href='#g3-101' y='208.035'/>
+<use x='212.089' xlink:href='#g3-114' y='208.035'/>
+<use x='214.981' xlink:href='#g3-41' y='208.035'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg b/extlib/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg
new file mode 100644 (file)
index 0000000..419dc25
--- /dev/null
@@ -0,0 +1,1028 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='255.738pt' version='1.1' viewBox='106.736 54.996 381.624 255.738' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip8'>
+<path d='M135.949 249.281H487.961V81.519H135.949Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-45' transform='scale(1.143)' xlink:href='#g0-45'/>
+<use id='g3-49' transform='scale(1.143)' xlink:href='#g0-49'/>
+<use id='g3-54' transform='scale(1.143)' xlink:href='#g0-54'/>
+<use id='g3-56' transform='scale(1.143)' xlink:href='#g0-56'/>
+<use id='g3-58' transform='scale(1.143)' xlink:href='#g0-58'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-103' transform='scale(1.143)' xlink:href='#g0-103'/>
+<use id='g3-104' transform='scale(1.143)' xlink:href='#g0-104'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-106' transform='scale(1.143)' xlink:href='#g0-106'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<use id='g3-120' transform='scale(1.143)' xlink:href='#g0-120'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g1-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g1-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-44' transform='scale(0.714)' xlink:href='#g0-44'/>
+<use id='g2-45' transform='scale(0.714)' xlink:href='#g0-45'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-64' transform='scale(0.714)' xlink:href='#g0-64'/>
+<use id='g2-67' transform='scale(0.714)' xlink:href='#g0-67'/>
+<use id='g2-71' transform='scale(0.714)' xlink:href='#g0-71'/>
+<use id='g2-73' transform='scale(0.714)' xlink:href='#g0-73'/>
+<use id='g2-85' transform='scale(0.714)' xlink:href='#g0-85'/>
+<use id='g2-88' transform='scale(0.714)' xlink:href='#g0-88'/>
+<use id='g2-97' transform='scale(0.714)' xlink:href='#g0-97'/>
+<use id='g2-98' transform='scale(0.714)' xlink:href='#g0-98'/>
+<use id='g2-99' transform='scale(0.714)' xlink:href='#g0-99'/>
+<use id='g2-100' transform='scale(0.714)' xlink:href='#g0-100'/>
+<use id='g2-101' transform='scale(0.714)' xlink:href='#g0-101'/>
+<use id='g2-103' transform='scale(0.714)' xlink:href='#g0-103'/>
+<use id='g2-104' transform='scale(0.714)' xlink:href='#g0-104'/>
+<use id='g2-108' transform='scale(0.714)' xlink:href='#g0-108'/>
+<use id='g2-109' transform='scale(0.714)' xlink:href='#g0-109'/>
+<use id='g2-110' transform='scale(0.714)' xlink:href='#g0-110'/>
+<use id='g2-111' transform='scale(0.714)' xlink:href='#g0-111'/>
+<use id='g2-112' transform='scale(0.714)' xlink:href='#g0-112'/>
+<use id='g2-114' transform='scale(0.714)' xlink:href='#g0-114'/>
+<use id='g2-115' transform='scale(0.714)' xlink:href='#g0-115'/>
+<use id='g2-116' transform='scale(0.714)' xlink:href='#g0-116'/>
+<use id='g2-117' transform='scale(0.714)' xlink:href='#g0-117'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<use id='g2-122' transform='scale(0.714)' xlink:href='#g0-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.007V-0.628H0.711V0H0.907L0.704 0.893H1.018L1.339 -0.007Z' id='g0-44'/>
+<path d='M2.05 -1.332V-1.771H0.084V-1.332H2.05Z' id='g0-45'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.339 -3.096H0.711V-2.469H1.339V-3.096ZM0.711 -0.628V0H1.339V-0.628H0.711Z' id='g0-58'/>
+<path d='M4.142 -0.614C4.038 -0.614 4.024 -0.614 3.968 -0.586C3.626 -0.467 3.271 -0.391 2.901 -0.391C1.778 -0.391 0.976 -1.339 0.976 -2.42C0.976 -3.592 1.883 -4.449 2.859 -4.449C3.055 -4.449 3.515 -4.4 3.745 -3.843C3.55 -3.954 3.333 -4.003 3.152 -4.003C2.406 -4.003 1.778 -3.306 1.778 -2.42C1.778 -1.513 2.427 -0.837 3.145 -0.837C3.689 -0.837 4.519 -1.276 4.519 -2.518C4.519 -3.222 4.47 -4.91 2.866 -4.91C1.541 -4.91 0.411 -3.815 0.411 -2.42C0.411 -1.039 1.527 0.07 2.873 0.07C3.515 0.07 4.115 -0.195 4.519 -0.614H4.142ZM3.152 -1.297C2.72 -1.297 2.343 -1.778 2.343 -2.42C2.343 -3.082 2.734 -3.543 3.145 -3.543C3.578 -3.543 3.954 -3.062 3.954 -2.42C3.954 -1.757 3.564 -1.297 3.152 -1.297Z' id='g0-64'/>
+<path d='M4.317 -0.851C3.829 -0.551 3.605 -0.418 2.908 -0.418C1.827 -0.418 1.172 -1.43 1.172 -2.434C1.172 -3.466 1.89 -4.435 2.908 -4.435C3.368 -4.435 3.843 -4.289 4.163 -4.045L4.275 -4.679C3.787 -4.861 3.396 -4.917 2.887 -4.917C1.506 -4.917 0.474 -3.773 0.474 -2.427C0.474 -0.99 1.569 0.07 2.929 0.07C3.612 0.07 3.898 -0.07 4.359 -0.321L4.317 -0.851Z' id='g0-67'/>
+<path d='M4.442 -2.085H2.88V-1.625H3.829V-0.558C3.522 -0.481 3.222 -0.418 2.908 -0.418C1.834 -0.418 1.172 -1.43 1.172 -2.427C1.172 -3.382 1.82 -4.435 2.873 -4.435C3.515 -4.435 3.919 -4.24 4.268 -3.947L4.38 -4.582C3.898 -4.812 3.473 -4.924 2.943 -4.924C1.534 -4.924 0.474 -3.822 0.474 -2.427C0.474 -1.067 1.527 0.07 2.901 0.07C3.403 0.07 3.996 -0.042 4.442 -0.272V-2.085Z' id='g0-71'/>
+<path d='M1.381 -4.84H0.676V0H1.381V-4.84Z' id='g0-73'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M4.4 -4.84H3.794V-1.625C3.794 -0.69 3.166 -0.265 2.566 -0.265S1.381 -0.697 1.381 -1.618V-4.84H0.676V-1.632C0.676 -0.607 1.555 0.146 2.559 0.146C3.557 0.146 4.4 -0.614 4.4 -1.632V-4.84Z' id='g0-85'/>
+<path d='M2.755 -2.552L4.519 -4.84H3.759L2.413 -3.055L1.039 -4.84H0.209L2.071 -2.552L0.105 0H0.865L2.413 -2.099L3.996 0H4.826L2.755 -2.552Z' id='g0-88'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M3.508 -3.166C3.354 -3.166 2.887 -3.159 2.357 -2.957L2.343 -2.95C2.092 -3.117 1.848 -3.166 1.646 -3.166C0.962 -3.166 0.453 -2.629 0.453 -2.029C0.453 -1.785 0.537 -1.534 0.697 -1.339C0.6 -1.22 0.495 -1.025 0.495 -0.76C0.495 -0.488 0.607 -0.314 0.669 -0.23C0.286 -0.007 0.209 0.314 0.209 0.481C0.209 1.011 0.941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 0.481C3.487 -0.502 2.267 -0.502 1.967 -0.502H1.318C1.206 -0.502 0.907 -0.502 0.907 -0.865C0.907 -1.004 0.955 -1.074 0.962 -1.088C1.206 -0.934 1.451 -0.886 1.639 -0.886C2.322 -0.886 2.831 -1.423 2.831 -2.022C2.831 -2.246 2.769 -2.448 2.643 -2.636C2.615 -2.678 2.615 -2.685 2.615 -2.692C2.615 -2.72 3.034 -2.72 3.068 -2.72C3.075 -2.72 3.34 -2.72 3.592 -2.692L3.508 -3.166ZM1.646 -1.318C1.269 -1.318 0.99 -1.555 0.99 -2.022C0.99 -2.566 1.339 -2.734 1.639 -2.734C2.015 -2.734 2.294 -2.497 2.294 -2.029C2.294 -1.485 1.946 -1.318 1.646 -1.318ZM1.974 0.042C2.134 0.042 2.957 0.042 2.957 0.488C2.957 0.788 2.434 0.997 1.848 0.997S0.739 0.788 0.739 0.488C0.739 0.453 0.739 0.042 1.304 0.042H1.974Z' id='g0-103'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.625 -3.166 1.304 -2.817 1.165 -2.671V-4.84H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-104'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.381 -4.784H0.676V-4.08H1.381V-4.784ZM-0.453 1.186C-0.133 1.36 0.181 1.423 0.446 1.423C0.928 1.423 1.381 1.053 1.381 0.411V-3.096H0.795V0.46C0.795 0.586 0.795 0.697 0.649 0.816C0.488 0.934 0.293 0.934 0.23 0.934C-0.063 0.934 -0.244 0.802 -0.328 0.725L-0.453 1.186Z' id='g0-106'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M3.243 -3.096H2.636V-1.074C2.636 -0.516 2.162 -0.342 1.757 -0.342C1.241 -0.342 1.186 -0.481 1.186 -0.802V-3.096H0.579V-0.76C0.579 -0.139 0.851 0.07 1.339 0.07C1.625 0.07 2.239 0.014 2.657 -0.321V0H3.243V-3.096Z' id='g0-117'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+<path d='M2.957 -2.803V-3.096H0.307V-2.65H1.332C1.416 -2.65 1.499 -2.657 1.583 -2.657H2.127L0.209 -0.307V0H2.978V-0.467H1.897C1.813 -0.467 1.73 -0.46 1.646 -0.46H1.039L2.957 -2.803Z' id='g0-122'/>
+</defs>
+<g id='page8'>
+<path d='M194.617 258.141V249.281M253.285 258.141V249.281M311.953 258.141V249.281M370.625 258.141V249.281M429.293 258.141V249.281M194.617 72.66V81.519M253.285 72.66V81.519M311.953 72.66V81.519M370.625 72.66V81.519M429.293 72.66V81.519' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 253.535V249.281M223.953 253.535V249.281M282.621 253.535V249.281M341.289 253.535V249.281M399.957 253.535V249.281M458.629 253.535V249.281M165.281 77.266V81.519M223.953 77.266V81.519M282.621 77.266V81.519M341.289 77.266V81.519M399.957 77.266V81.519M458.629 77.266V81.519' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281H140.199M135.949 215.73H140.199M135.949 182.176H140.199M135.949 148.625H140.199M135.949 115.07H140.199M135.949 81.519H140.199M487.961 249.281H483.711M487.961 215.73H483.711M487.961 182.176H483.711M487.961 148.625H483.711M487.961 115.07H483.711M487.961 81.519H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281V81.519H487.961V249.281H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='188.688'/>
+<use x='172.353' xlink:href='#g3-108' y='188.688'/>
+<use x='174.373' xlink:href='#g3-108' y='188.688'/>
+<use x='176.393' xlink:href='#g3-111' y='188.688'/>
+<use x='180.863' xlink:href='#g3-99' y='188.688'/>
+<use x='184.627' xlink:href='#g3-45' y='188.688'/>
+<use x='187.449' xlink:href='#g3-116' y='188.688'/>
+<use x='190.507' xlink:href='#g3-101' y='188.688'/>
+<use x='194.271' xlink:href='#g3-115' y='188.688'/>
+<use x='197.517' xlink:href='#g3-116' y='188.688'/>
+<use x='200.575' xlink:href='#g3-49' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='188.688'/>
+<use x='172.353' xlink:href='#g3-108' y='188.688'/>
+<use x='174.373' xlink:href='#g3-108' y='188.688'/>
+<use x='176.393' xlink:href='#g3-111' y='188.688'/>
+<use x='180.863' xlink:href='#g3-99' y='188.688'/>
+<use x='184.627' xlink:href='#g3-45' y='188.688'/>
+<use x='187.449' xlink:href='#g3-116' y='188.688'/>
+<use x='190.507' xlink:href='#g3-101' y='188.688'/>
+<use x='194.271' xlink:href='#g3-115' y='188.688'/>
+<use x='197.517' xlink:href='#g3-116' y='188.688'/>
+<use x='200.575' xlink:href='#g3-78' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='188.688'/>
+<use x='171.531' xlink:href='#g3-104' y='188.688'/>
+<use x='175.904' xlink:href='#g3-54' y='188.688'/>
+<use x='180.138' xlink:href='#g3-98' y='188.688'/>
+<use x='184.746' xlink:href='#g3-101' y='188.688'/>
+<use x='188.509' xlink:href='#g3-110' y='188.688'/>
+<use x='192.882' xlink:href='#g3-99' y='188.688'/>
+<use x='196.646' xlink:href='#g3-104' y='188.688'/>
+<use x='201.018' xlink:href='#g3-78' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='188.688'/>
+<use x='171.531' xlink:href='#g3-104' y='188.688'/>
+<use x='175.904' xlink:href='#g3-56' y='188.688'/>
+<use x='180.138' xlink:href='#g3-98' y='188.688'/>
+<use x='184.746' xlink:href='#g3-101' y='188.688'/>
+<use x='188.509' xlink:href='#g3-110' y='188.688'/>
+<use x='192.882' xlink:href='#g3-99' y='188.688'/>
+<use x='196.646' xlink:href='#g3-104' y='188.688'/>
+<use x='201.018' xlink:href='#g3-78' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' xlink:href='#g3-120' y='188.688'/>
+<use x='172.187' xlink:href='#g3-109' y='188.688'/>
+<use x='178.912' xlink:href='#g3-97' y='188.688'/>
+<use x='182.98' xlink:href='#g3-108' y='188.688'/>
+<use x='185' xlink:href='#g3-108' y='188.688'/>
+<use x='187.02' xlink:href='#g3-111' y='188.688'/>
+<use x='191.49' xlink:href='#g3-99' y='188.688'/>
+<use x='195.254' xlink:href='#g3-45' y='188.688'/>
+<use x='198.076' xlink:href='#g3-116' y='188.688'/>
+<use x='201.134' xlink:href='#g3-101' y='188.688'/>
+<use x='204.898' xlink:href='#g3-115' y='188.688'/>
+<use x='208.144' xlink:href='#g3-116' y='188.688'/>
+<use x='211.202' xlink:href='#g3-78' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' xlink:href='#g3-99' y='188.688'/>
+<use x='172.049' xlink:href='#g3-97' y='188.688'/>
+<use x='176.117' xlink:href='#g3-99' y='188.688'/>
+<use x='179.88' xlink:href='#g3-104' y='188.688'/>
+<use x='184.253' xlink:href='#g3-101' y='188.688'/>
+<use x='188.017' xlink:href='#g3-45' y='188.688'/>
+<use x='190.839' xlink:href='#g3-115' y='188.688'/>
+<use x='194.086' xlink:href='#g3-99' y='188.688'/>
+<use x='197.849' xlink:href='#g3-114' y='188.688'/>
+<use x='200.741' xlink:href='#g3-97' y='188.688'/>
+<use x='204.81' xlink:href='#g3-116' y='188.688'/>
+<use x='207.868' xlink:href='#g3-99' y='188.688'/>
+<use x='211.631' xlink:href='#g3-104' y='188.688'/>
+<use x='216.004' xlink:href='#g3-78' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' xlink:href='#g2-50' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' xlink:href='#g2-50' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-120' y='188.688'/>
+</g>
+<path clip-path='url(#clip8)' d='M135.949 182.176H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M142.742 249.281H145.981V182.176H142.742ZM201.41 249.281H204.649V182.176H201.41ZM260.078 249.281H263.317V182.176H260.078ZM318.75 249.281H321.988V182.176H318.75ZM377.418 249.281H380.656V182.176H377.418ZM436.086 249.281H439.324V182.176H436.086Z' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M142.742 249.281H145.981V182.176H142.742ZM201.41 249.281H204.649V182.176H201.41ZM260.078 249.281H263.317V182.176H260.078ZM318.75 249.281H321.988V182.176H318.75ZM377.418 249.281H380.656V182.176H377.418ZM436.086 249.281H439.324V182.176H436.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M144.359 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M142.367 182.176H146.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M144.359 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M142.367 182.176H146.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M203.031 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M201.035 182.176H205.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M203.031 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M201.035 182.176H205.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M261.699 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M259.707 182.176H263.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M261.699 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M259.707 182.176H263.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M320.367 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M318.375 182.176H322.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M320.367 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M318.375 182.176H322.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M379.035 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M377.043 182.176H381.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M379.035 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M377.043 182.176H381.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M437.707 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M435.711 182.176H439.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M437.707 182.176V182.176' fill='#ffffff'/>
+<path clip-path='url(#clip8)' d='M435.711 182.176H439.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M147.973 249.281H151.211V164.73H147.973ZM206.641 249.281H209.879V161.977H206.641ZM265.309 249.281H268.547V183.25H265.309ZM323.981 249.281H327.219V209.891H323.981ZM382.649 249.281H385.887V224.184H382.649ZM441.317 249.281H444.555V141.242H441.317Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M147.973 249.281H151.211V164.73H147.973ZM206.641 249.281H209.879V161.977H206.641ZM265.309 249.281H268.547V183.25H265.309ZM323.981 249.281H327.219V209.891H323.981ZM382.649 249.281H385.887V224.184H382.649ZM441.317 249.281H444.555V141.242H441.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M149.59 164.73V164.73' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M147.598 164.73H151.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M149.59 164.73V164.73' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M147.598 164.73H151.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M208.262 161.977V161.977' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M206.266 161.976H210.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M208.262 161.977V161.977' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M206.266 161.976H210.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M266.93 183.25V183.25' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M264.938 183.25H268.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M266.93 183.25V183.25' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M264.938 183.25H268.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M325.598 209.891V209.891' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M323.606 209.891H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M325.598 209.891V209.891' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M323.606 209.891H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M384.266 224.184V224.184' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M382.274 224.183H386.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M384.266 224.184V224.184' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M382.274 224.183H386.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M442.938 141.242V141.242' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M440.942 141.242H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M442.938 141.242V141.242' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M440.942 141.242H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M153.203 249.281H156.442V185.129H153.203ZM211.871 249.281H215.11V177.883H211.871ZM270.539 249.281H273.777V181.437H270.539ZM329.211 249.281H332.449V192.848H329.211ZM387.879 249.281H391.117V183.719H387.879ZM446.547 249.281H449.785V145H446.547Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M153.203 249.281H156.442V185.129H153.203ZM211.871 249.281H215.11V177.883H211.871ZM270.539 249.281H273.777V181.437H270.539ZM329.211 249.281H332.449V192.848H329.211ZM387.879 249.281H391.117V183.719H387.879ZM446.547 249.281H449.785V145H446.547Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M154.82 185.129V185.129' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M152.828 185.129H156.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M154.82 185.129V185.129' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M152.828 185.129H156.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M213.492 177.883V177.883' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M211.496 177.883H215.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M213.492 177.883V177.883' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M211.496 177.883H215.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M272.16 181.437V181.437' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M270.168 181.438H274.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M272.16 181.437V181.437' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M270.168 181.438H274.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M330.828 192.848V192.848' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M328.836 192.848H332.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M330.828 192.848V192.848' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M328.836 192.848H332.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M389.496 183.719V183.719' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M387.504 183.718H391.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M389.496 183.719V183.719' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M387.504 183.718H391.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M448.168 145V145' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M446.172 145H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M448.168 145V145' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M446.172 145H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M158.434 249.281H161.672V180.969H158.434ZM217.102 249.281H220.34V172.043H217.102ZM275.77 249.281H279.008V172.312H275.77ZM334.442 249.281H337.68V194.996H334.442ZM393.109 249.281H396.348V195.531H393.109ZM451.777 249.281H455.016V180.098H451.777Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M158.434 249.281H161.672V180.969H158.434ZM217.102 249.281H220.34V172.043H217.102ZM275.77 249.281H279.008V172.312H275.77ZM334.442 249.281H337.68V194.996H334.442ZM393.109 249.281H396.348V195.531H393.109ZM451.777 249.281H455.016V180.098H451.777Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M160.051 180.969V180.969' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M158.058 180.969H162.042' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M160.051 180.969V180.969' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M158.058 180.969H162.042' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M218.723 172.043V172.043' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M216.726 172.043H220.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M218.723 172.043V172.043' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M216.726 172.043H220.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M277.391 172.312V172.312' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M275.398 172.312H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M277.391 172.312V172.312' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M275.398 172.312H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M336.059 194.996V194.996' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M334.066 194.996H338.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M336.059 194.996V194.996' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M334.066 194.996H338.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M394.727 195.531V195.531' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M392.734 195.531H396.718' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M394.727 195.531V195.531' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M392.734 195.531H396.718' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M453.399 180.098V180.098' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M451.402 180.098H455.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M453.399 180.098V180.098' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M451.402 180.098H455.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M163.664 249.281H166.903V180.363H163.664ZM222.332 249.281H225.57V144.465H222.332ZM281 249.281H284.238V171.707H281ZM339.672 249.281H342.91V191.641H339.672ZM398.34 249.281H401.578V81.519H398.34ZM457.008 249.281H460.246V190.027H457.008Z' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M163.664 249.281H166.903V180.363H163.664ZM222.332 249.281H225.57V144.465H222.332ZM281 249.281H284.238V171.707H281ZM339.672 249.281H342.91V191.641H339.672ZM398.34 249.281H401.578V81.519H398.34ZM457.008 249.281H460.246V190.027H457.008Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M165.281 180.363V180.363' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M163.289 180.363H167.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M165.281 180.363V180.363' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M163.289 180.363H167.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M223.953 144.465V144.465' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M221.957 144.464H225.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M223.953 144.465V144.465' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M221.957 144.464H225.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M282.621 171.707V171.707' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M280.629 171.707H284.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M282.621 171.707V171.707' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M280.629 171.707H284.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M341.289 191.641V191.641' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M339.297 191.641H343.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M341.289 191.641V191.641' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M339.297 191.641H343.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M399.957 81.519V81.519' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M397.965 81.52H401.949' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M399.957 81.519V81.519' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M397.965 81.52H401.949' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M458.629 190.027V190.027' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M456.633 190.027H460.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M458.629 190.027V190.027' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M456.633 190.027H460.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M168.895 249.281H172.133V157.348H168.895ZM227.563 249.281H230.801V81.519H227.563ZM286.231 249.281H289.469V141.711H286.231ZM344.902 249.281H348.141V124.601H344.902ZM403.57 249.281H406.809V132.25H403.57ZM462.238 249.281H465.477V189.894H462.238Z' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M168.895 249.281H172.133V157.348H168.895ZM227.563 249.281H230.801V81.519H227.563ZM286.231 249.281H289.469V141.711H286.231ZM344.902 249.281H348.141V124.601H344.902ZM403.57 249.281H406.809V132.25H403.57ZM462.238 249.281H465.477V189.894H462.238Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M170.512 157.348V157.348' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M168.519 157.348H172.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M170.512 157.348V157.348' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M168.519 157.348H172.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M229.184 81.519V81.519' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M227.187 81.52H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M229.184 81.519V81.519' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M227.187 81.52H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M287.852 141.711V141.711' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M285.859 141.711H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M287.852 141.711V141.711' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M285.859 141.711H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M346.52 124.601V124.601' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M344.527 124.602H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M346.52 124.601V124.601' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M344.527 124.602H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M405.188 132.25V132.25' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M403.195 132.25H407.179' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M405.188 132.25V132.25' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M403.195 132.25H407.179' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M463.859 189.894V189.894' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M461.863 189.894H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M463.859 189.894V189.894' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M461.863 189.894H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M174.125 249.281H177.363V171.574H174.125ZM232.793 249.281H236.031V146.344H232.793ZM291.461 249.281H294.699V169.426H291.461ZM350.133 249.281H353.371V204.254H350.133ZM408.801 249.281H412.039V224.992H408.801ZM467.469 249.281H470.707V163.254H467.469Z' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M174.125 249.281H177.363V171.574H174.125ZM232.793 249.281H236.031V146.344H232.793ZM291.461 249.281H294.699V169.426H291.461ZM350.133 249.281H353.371V204.254H350.133ZM408.801 249.281H412.039V224.992H408.801ZM467.469 249.281H470.707V163.254H467.469Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M175.742 171.574V171.574' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M173.75 171.574H177.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M175.742 171.574V171.574' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M173.75 171.574H177.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M234.414 146.344V146.344' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M232.418 146.343H236.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M234.414 146.344V146.344' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M232.418 146.343H236.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M293.082 169.426V169.426' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M291.09 169.426H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M293.082 169.426V169.426' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M291.09 169.426H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M351.75 204.254V204.254' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M349.758 204.254H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M351.75 204.254V204.254' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M349.758 204.254H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M410.418 224.992V224.992' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M408.426 224.992H412.41' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M410.418 224.992V224.992' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M408.426 224.992H412.41' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M469.09 163.254V163.254' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M467.094 163.254H471.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M469.09 163.254V163.254' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M467.094 163.254H471.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M179.356 249.281H182.594V176.004H179.356ZM238.024 249.281H241.262V169.16H238.024ZM296.692 249.281H299.93V149.699H296.692ZM355.363 249.281H358.602V121.043H355.363ZM414.031 249.281H417.27V214.051H414.031ZM472.699 249.281H475.938V194.121H472.699Z' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M179.356 249.281H182.594V176.004H179.356ZM238.024 249.281H241.262V169.16H238.024ZM296.692 249.281H299.93V149.699H296.692ZM355.363 249.281H358.602V121.043H355.363ZM414.031 249.281H417.27V214.051H414.031ZM472.699 249.281H475.938V194.121H472.699Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M180.973 176.004V176.004' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M178.98 176.004H182.965' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M180.973 176.004V176.004' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M178.98 176.004H182.965' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M239.645 169.16V169.16' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M237.648 169.16H241.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M239.645 169.16V169.16' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M237.648 169.16H241.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M298.313 149.699V149.699' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M296.32 149.7H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M298.313 149.699V149.699' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M296.32 149.7H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M356.981 121.043V121.043' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M354.988 121.043H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M356.981 121.043V121.043' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M354.988 121.043H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M415.649 214.051V214.051' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M413.656 214.05H417.64' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M415.649 214.051V214.051' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M413.656 214.05H417.64' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M474.32 194.121V194.121' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M472.324 194.121H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M474.32 194.121V194.121' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M472.324 194.121H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M184.586 249.281H187.824V181.641H184.586ZM243.254 249.281H246.492V115.137H243.254ZM301.922 249.281H305.16V176.605H301.922ZM360.594 249.281H363.832V185.734H360.594ZM419.262 249.281H422.5V164.125H419.262ZM477.93 249.281H481.168V179.828H477.93Z' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M184.586 249.281H187.824V181.641H184.586ZM243.254 249.281H246.492V115.137H243.254ZM301.922 249.281H305.16V176.605H301.922ZM360.594 249.281H363.832V185.734H360.594ZM419.262 249.281H422.5V164.125H419.262ZM477.93 249.281H481.168V179.828H477.93Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M186.203 181.641V181.641' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M184.211 181.64H188.196' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M186.203 181.641V181.641' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M184.211 181.64H188.196' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M244.875 115.137V115.137' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M242.879 115.137H246.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M244.875 115.137V115.137' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M242.879 115.137H246.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M303.543 176.605V176.605' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M301.551 176.605H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M303.543 176.605V176.605' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M301.551 176.605H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M362.211 185.734V185.734' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M360.219 185.735H364.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M362.211 185.734V185.734' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M360.219 185.735H364.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M420.879 164.125V164.125' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M418.887 164.125H422.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M420.879 164.125V164.125' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M418.887 164.125H422.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M479.551 179.828V179.828' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M477.555 179.828H481.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M479.551 179.828V179.828' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M477.555 179.828H481.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M420.539 310.336H487.762V276.324H420.539Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 255.575 118.327)'>
+<use x='168.285' xlink:href='#g2-99' y='164.777'/>
+<use x='170.637' xlink:href='#g2-53' y='164.777'/>
+<use x='173.284' xlink:href='#g2-45' y='164.777'/>
+<use x='175.048' xlink:href='#g2-49' y='164.777'/>
+<use x='177.694' xlink:href='#g2-56' y='164.777'/>
+<use x='180.341' xlink:href='#g2-120' y='164.777'/>
+<use x='182.779' xlink:href='#g2-108' y='164.777'/>
+<use x='184.042' xlink:href='#g2-97' y='164.777'/>
+<use x='186.438' xlink:href='#g2-114' y='164.777'/>
+<use x='188.245' xlink:href='#g2-103' y='164.777'/>
+<use x='190.891' xlink:href='#g2-101' y='164.777'/>
+<use x='193.244' xlink:href='#g2-44' y='164.777'/>
+<use x='196.478' xlink:href='#g2-49' y='164.777'/>
+<use x='199.124' xlink:href='#g2-52' y='164.777'/>
+<use x='201.771' xlink:href='#g2-52' y='164.777'/>
+<use x='204.417' xlink:href='#g2-71' y='164.777'/>
+<use x='207.946' xlink:href='#g2-98' y='164.777'/>
+<use x='168.285' xlink:href='#g2-55' y='170.755'/>
+<use x='170.931' xlink:href='#g2-50' y='170.755'/>
+<use x='175.342' xlink:href='#g2-112' y='170.755'/>
+<use x='177.928' xlink:href='#g2-114' y='170.755'/>
+<use x='179.735' xlink:href='#g2-111' y='170.755'/>
+<use x='182.529' xlink:href='#g2-99' y='170.755'/>
+<use x='186.645' xlink:href='#g2-73' y='170.755'/>
+<use x='188.115' xlink:href='#g2-110' y='170.755'/>
+<use x='190.848' xlink:href='#g2-116' y='170.755'/>
+<use x='192.759' xlink:href='#g2-101' y='170.755'/>
+<use x='195.112' xlink:href='#g2-108' y='170.755'/>
+<use x='198.139' xlink:href='#g2-88' y='170.755'/>
+<use x='201.667' xlink:href='#g2-101' y='170.755'/>
+<use x='204.019' xlink:href='#g2-111' y='170.755'/>
+<use x='206.666' xlink:href='#g2-110' y='170.755'/>
+<use x='211.163' xlink:href='#g2-64' y='170.755'/>
+<use x='214.691' xlink:href='#g2-51' y='170.755'/>
+<use x='217.338' xlink:href='#g2-71' y='170.755'/>
+<use x='220.866' xlink:href='#g2-104' y='170.755'/>
+<use x='223.599' xlink:href='#g2-122' y='170.755'/>
+<use x='168.285' xlink:href='#g2-85' y='176.733'/>
+<use x='171.917' xlink:href='#g2-98' y='176.733'/>
+<use x='174.65' xlink:href='#g2-117' y='176.733'/>
+<use x='177.383' xlink:href='#g2-110' y='176.733'/>
+<use x='180.116' xlink:href='#g2-116' y='176.733'/>
+<use x='182.027' xlink:href='#g2-117' y='176.733'/>
+<use x='186.524' xlink:href='#g2-49' y='176.733'/>
+<use x='189.17' xlink:href='#g2-56' y='176.733'/>
+<use x='191.817' xlink:href='#g2-46' y='176.733'/>
+<use x='193.287' xlink:href='#g2-48' y='176.733'/>
+<use x='195.933' xlink:href='#g2-52' y='176.733'/>
+<use x='198.58' xlink:href='#g2-46' y='176.733'/>
+<use x='200.05' xlink:href='#g2-49' y='176.733'/>
+<use x='202.696' xlink:href='#g2-44' y='176.733'/>
+<use x='205.931' xlink:href='#g2-71' y='176.733'/>
+<use x='209.459' xlink:href='#g2-67' y='176.733'/>
+<use x='212.841' xlink:href='#g2-67' y='176.733'/>
+<use x='217.986' xlink:href='#g2-55' y='176.733'/>
+<use x='220.633' xlink:href='#g2-46' y='176.733'/>
+<use x='222.103' xlink:href='#g2-52' y='176.733'/>
+<use x='224.749' xlink:href='#g2-46' y='176.733'/>
+<use x='226.219' xlink:href='#g2-48' y='176.733'/>
+<use x='168.285' xlink:href='#g2-51' y='182.71'/>
+<use x='170.931' xlink:href='#g2-54' y='182.71'/>
+<use x='175.342' xlink:href='#g2-99' y='182.71'/>
+<use x='177.694' xlink:href='#g2-111' y='182.71'/>
+<use x='180.193' xlink:href='#g2-114' y='182.71'/>
+<use x='182.001' xlink:href='#g2-101' y='182.71'/>
+<use x='184.353' xlink:href='#g2-115' y='182.71'/>
+<use x='188.146' xlink:href='#g2-111' y='182.71'/>
+<use x='190.793' xlink:href='#g2-110' y='182.71'/>
+<use x='195.29' xlink:href='#g2-50' y='182.71'/>
+<use x='199.7' xlink:href='#g2-110' y='182.71'/>
+<use x='202.433' xlink:href='#g2-117' y='182.71'/>
+<use x='205.166' xlink:href='#g2-109' y='182.71'/>
+<use x='209.369' xlink:href='#g2-97' y='182.71'/>
+<use x='213.676' xlink:href='#g2-110' y='182.71'/>
+<use x='216.409' xlink:href='#g2-111' y='182.71'/>
+<use x='219.202' xlink:href='#g2-100' y='182.71'/>
+<use x='221.935' xlink:href='#g2-101' y='182.71'/>
+<use x='224.287' xlink:href='#g2-115' y='182.71'/>
+<use x='168.285' xlink:href='#g2-50' y='188.688'/>
+<use x='170.931' xlink:href='#g2-48' y='188.688'/>
+<use x='173.578' xlink:href='#g2-50' y='188.688'/>
+<use x='176.224' xlink:href='#g2-48' y='188.688'/>
+<use x='178.87' xlink:href='#g2-45' y='188.688'/>
+<use x='180.635' xlink:href='#g2-48' y='188.688'/>
+<use x='183.281' xlink:href='#g2-49' y='188.688'/>
+<use x='185.927' xlink:href='#g2-45' y='188.688'/>
+<use x='187.692' xlink:href='#g2-49' y='188.688'/>
+<use x='190.338' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -42.693 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 15.976 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.645 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.314 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 191.983 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 250.652 344.258)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -37.462 326.81)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-50' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.207 324.059)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-51' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.876 345.332)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-57' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.545 371.973)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-57' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.214 386.266)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-51' y='188.688'/>
+<use x='175.048' xlink:href='#g2-55' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 255.882 303.323)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-54' y='188.688'/>
+<use x='175.048' xlink:href='#g2-49' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.232 347.211)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-57' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.437 339.963)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.106 343.52)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-49' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.775 354.928)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-52' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.444 345.801)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-57' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.113 307.081)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-53' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -27.002 343.05)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-50' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.667 334.125)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-53' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.336 334.393)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-53' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 149.005 357.075)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-49' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.674 357.612)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 266.343 342.178)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-51' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -21.771 342.446)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-51' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.898 306.544)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.567 333.789)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 154.236 353.72)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.905 243.599)'>
+<use x='163.396' xlink:href='#g4-1' y='188.688'/>
+<use x='166.901' xlink:href='#g4-1' y='188.688'/>
+<use x='170.407' xlink:href='#g4-1' y='188.688'/>
+<use x='173.912' xlink:href='#g2-50' y='188.688'/>
+<use x='176.558' xlink:href='#g2-55' y='188.688'/>
+<use x='179.205' xlink:href='#g2-46' y='188.688'/>
+<use x='180.675' xlink:href='#g2-51' y='188.688'/>
+<use x='183.321' xlink:href='#g2-51' y='188.688'/>
+<use x='185.968' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 271.574 352.109)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.541 319.429)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-51' y='188.688'/>
+<use x='175.048' xlink:href='#g2-55' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 42.128 243.599)'>
+<use x='163.396' xlink:href='#g4-1' y='188.688'/>
+<use x='166.901' xlink:href='#g4-1' y='188.688'/>
+<use x='170.407' xlink:href='#g4-1' y='188.688'/>
+<use x='173.912' xlink:href='#g2-51' y='188.688'/>
+<use x='176.558' xlink:href='#g2-46' y='188.688'/>
+<use x='178.029' xlink:href='#g2-51' y='188.688'/>
+<use x='180.675' xlink:href='#g2-54' y='188.688'/>
+<use x='183.321' xlink:href='#g2-120' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.797 303.793)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-54' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.466 286.681)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 218.135 294.331)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-55' y='188.688'/>
+<use x='175.048' xlink:href='#g2-52' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 276.804 351.975)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-57' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -11.31 333.655)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 47.359 308.423)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-51' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 106.028 331.508)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-57' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 164.697 366.336)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-54' y='188.688'/>
+<use x='175.048' xlink:href='#g2-55' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 223.366 387.072)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-51' y='188.688'/>
+<use x='175.048' xlink:href='#g2-54' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 282.035 325.334)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-50' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -6.08 338.084)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-57' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 52.589 331.239)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-49' y='188.688'/>
+<use x='175.048' xlink:href='#g2-57' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 111.258 311.779)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-52' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 169.927 283.124)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-57' y='188.688'/>
+<use x='175.048' xlink:href='#g2-49' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 228.596 376.133)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-53' y='188.688'/>
+<use x='175.048' xlink:href='#g2-50' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 287.265 356.203)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-56' y='188.688'/>
+<use x='175.048' xlink:href='#g2-50' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -0.849 343.721)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-49' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 57.82 277.219)'>
+<use x='168.285' xlink:href='#g2-50' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-48' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 116.489 338.688)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-56' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 175.158 347.815)'>
+<use x='168.285' xlink:href='#g2-48' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-57' y='188.688'/>
+<use x='175.048' xlink:href='#g2-53' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 233.827 326.206)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-50' y='188.688'/>
+<use x='175.048' xlink:href='#g2-55' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 292.496 341.909)'>
+<use x='168.285' xlink:href='#g2-49' y='188.688'/>
+<use x='170.931' xlink:href='#g2-46' y='188.688'/>
+<use x='172.401' xlink:href='#g2-48' y='188.688'/>
+<use x='175.048' xlink:href='#g2-52' y='188.688'/>
+</g>
+<g transform='matrix(0 -1 1 0 -75.53 385.58)'>
+<use x='168.285' xlink:href='#g1-82' y='188.688'/>
+<use x='174.255' xlink:href='#g1-101' y='188.688'/>
+<use x='178.351' xlink:href='#g1-108' y='188.688'/>
+<use x='180.551' xlink:href='#g1-97' y='188.688'/>
+<use x='184.979' xlink:href='#g1-116' y='188.688'/>
+<use x='188.307' xlink:href='#g1-105' y='188.688'/>
+<use x='190.507' xlink:href='#g1-118' y='188.688'/>
+<use x='194.755' xlink:href='#g1-101' y='188.688'/>
+<use x='201.922' xlink:href='#g1-114' y='188.688'/>
+<use x='205.07' xlink:href='#g1-115' y='188.688'/>
+<use x='208.603' xlink:href='#g1-115' y='188.688'/>
+<use x='215.207' xlink:href='#g3-40' y='188.688'/>
+<use x='218.5' xlink:href='#g3-108' y='188.688'/>
+<use x='220.521' xlink:href='#g3-111' y='188.688'/>
+<use x='224.52' xlink:href='#g3-119' y='188.688'/>
+<use x='230.068' xlink:href='#g3-101' y='188.688'/>
+<use x='233.832' xlink:href='#g3-114' y='188.688'/>
+<use x='239.547' xlink:href='#g3-105' y='188.688'/>
+<use x='241.567' xlink:href='#g3-115' y='188.688'/>
+<use x='247.636' xlink:href='#g3-98' y='188.688'/>
+<use x='252.244' xlink:href='#g3-101' y='188.688'/>
+<use x='256.008' xlink:href='#g3-116' y='188.688'/>
+<use x='259.066' xlink:href='#g3-116' y='188.688'/>
+<use x='262.124' xlink:href='#g3-101' y='188.688'/>
+<use x='265.887' xlink:href='#g3-114' y='188.688'/>
+<use x='268.779' xlink:href='#g3-41' y='188.688'/>
+</g>
+<path d='M136.149 309.68H341.363V279.68H136.149Z' fill='#ffffff'/>
+<path d='M136.149 309.68H341.363V279.68H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='#ffffff'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='195.372' xlink:href='#g3-120' y='175.681'/>
+<use x='199.274' xlink:href='#g3-109' y='175.681'/>
+<use x='205.999' xlink:href='#g3-105' y='175.681'/>
+<use x='208.019' xlink:href='#g3-58' y='175.681'/>
+<use x='210.371' xlink:href='#g0-54' y='175.681'/>
+<use x='214.076' xlink:href='#g0-57' y='175.681'/>
+</g>
+<path d='M184.145 290.168H187.133V282.199H184.145ZM190.121 290.168H193.109V284.191H190.121Z' fill='#f0e0f0'/>
+<path d='M184.145 290.168H187.133V282.199H184.145ZM190.121 290.168H193.109V284.191H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='239.382' xlink:href='#g3-116' y='175.681'/>
+<use x='242.44' xlink:href='#g3-99' y='175.681'/>
+<use x='246.204' xlink:href='#g3-58' y='175.681'/>
+<use x='248.556' xlink:href='#g0-54' y='175.681'/>
+<use x='252.261' xlink:href='#g0-54' y='175.681'/>
+</g>
+<path d='M227.356 290.168H230.344V282.199H227.356ZM233.332 290.168H236.32V284.191H233.332Z' fill='#e1c2e1'/>
+<path d='M227.356 290.168H230.344V282.199H227.356ZM233.332 290.168H236.32V284.191H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='281.863' xlink:href='#g3-106' y='175.681'/>
+<use x='284.119' xlink:href='#g3-101' y='175.681'/>
+<use x='287.882' xlink:href='#g3-58' y='175.681'/>
+<use x='290.235' xlink:href='#g0-54' y='175.681'/>
+<use x='293.94' xlink:href='#g0-54' y='175.681'/>
+</g>
+<path d='M269.106 290.168H272.094V282.199H269.106ZM275.086 290.168H278.074V284.191H275.086Z' fill='#d1a3d1'/>
+<path d='M269.106 290.168H272.094V282.199H269.106ZM275.086 290.168H278.074V284.191H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='321.287' xlink:href='#g3-116' y='175.681'/>
+<use x='324.345' xlink:href='#g3-98' y='175.681'/>
+<use x='328.717' xlink:href='#g3-98' y='175.681'/>
+<use x='333.09' xlink:href='#g3-58' y='175.681'/>
+<use x='335.442' xlink:href='#g0-54' y='175.681'/>
+<use x='339.147' xlink:href='#g0-53' y='175.681'/>
+</g>
+<path d='M306.203 290.168H309.191V282.199H306.203ZM312.18 290.168H315.168V284.191H312.18Z' fill='#c285c2'/>
+<path d='M306.203 290.168H309.191V282.199H306.203ZM312.18 290.168H315.168V284.191H312.18Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='356.019' xlink:href='#g3-114' y='175.681'/>
+<use x='358.911' xlink:href='#g3-112' y='175.681'/>
+<use x='363.284' xlink:href='#g3-58' y='175.681'/>
+<use x='365.636' xlink:href='#g0-52' y='175.681'/>
+<use x='369.341' xlink:href='#g0-52' y='175.681'/>
+</g>
+<path d='M139.336 303.176H142.324V295.207H139.336ZM145.313 303.176H148.301V297.199H145.313Z' fill='#b366b3'/>
+<path d='M139.336 303.176H142.324V295.207H139.336ZM145.313 303.176H148.301V297.199H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='195.372' xlink:href='#g3-104' y='188.688'/>
+<use x='199.744' xlink:href='#g3-111' y='188.688'/>
+<use x='203.978' xlink:href='#g3-97' y='188.688'/>
+<use x='207.811' xlink:href='#g3-114' y='188.688'/>
+<use x='210.703' xlink:href='#g3-100' y='188.688'/>
+<use x='215.076' xlink:href='#g3-58' y='188.688'/>
+<use x='217.428' xlink:href='#g0-51' y='188.688'/>
+<use x='221.133' xlink:href='#g0-54' y='188.688'/>
+</g>
+<path d='M184.145 303.176H187.133V295.207H184.145ZM190.121 303.176H193.109V297.199H190.121Z' fill='#a447a4'/>
+<path d='M184.145 303.176H187.133V295.207H184.145ZM190.121 303.176H193.109V297.199H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='239.382' xlink:href='#g3-109' y='188.688'/>
+<use x='246.107' xlink:href='#g3-101' y='188.688'/>
+<use x='249.871' xlink:href='#g3-115' y='188.688'/>
+<use x='253.117' xlink:href='#g3-104' y='188.688'/>
+<use x='257.489' xlink:href='#g3-58' y='188.688'/>
+<use x='259.842' xlink:href='#g0-54' y='188.688'/>
+<use x='263.547' xlink:href='#g0-49' y='188.688'/>
+</g>
+<path d='M227.356 303.176H230.344V295.207H227.356ZM233.332 303.176H236.32V297.199H233.332Z' fill='#942994'/>
+<path d='M227.356 303.176H230.344V295.207H227.356ZM233.332 303.176H236.32V297.199H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='281.863' xlink:href='#g3-103' y='188.688'/>
+<use x='286.097' xlink:href='#g3-108' y='188.688'/>
+<use x='288.118' xlink:href='#g3-105' y='188.688'/>
+<use x='290.138' xlink:href='#g3-98' y='188.688'/>
+<use x='294.746' xlink:href='#g3-99' y='188.688'/>
+<use x='298.509' xlink:href='#g3-58' y='188.688'/>
+<use x='300.862' xlink:href='#g0-54' y='188.688'/>
+<use x='304.567' xlink:href='#g0-52' y='188.688'/>
+</g>
+<path d='M269.106 303.176H272.094V295.207H269.106ZM275.086 303.176H278.074V297.199H275.086Z' fill='#850a85'/>
+<path d='M269.106 303.176H272.094V295.207H269.106ZM275.086 303.176H278.074V297.199H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='321.287' xlink:href='#g3-115' y='188.688'/>
+<use x='324.533' xlink:href='#g3-109' y='188.688'/>
+<use x='331.258' xlink:href='#g3-105' y='188.688'/>
+<use x='333.278' xlink:href='#g3-58' y='188.688'/>
+<use x='335.63' xlink:href='#g0-52' y='188.688'/>
+<use x='339.335' xlink:href='#g0-53' y='188.688'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-1.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-1.svg
new file mode 100644 (file)
index 0000000..c296a04
--- /dev/null
@@ -0,0 +1,769 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='164.687pt' version='1.1' viewBox='52.938 54.996 381.625 164.687' width='381.625pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip1'>
+<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-102' transform='scale(1.6)' xlink:href='#g1-102'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M0.946 -1.898H1.514V-2.212H0.932V-2.785C0.932 -3.128 1.245 -3.178 1.41 -3.178C1.514 -3.178 1.649 -3.163 1.833 -3.093V-3.457C1.704 -3.487 1.549 -3.507 1.415 -3.507C0.902 -3.507 0.528 -3.138 0.528 -2.645V-2.212H0.144V-1.898H0.528V0H0.946V-1.898Z' id='g1-102'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g0-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page1'>
+<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 33.989)'>
+<use x='114.487' xlink:href='#g2-99' y='183.949'/>
+<use x='118.25' xlink:href='#g2-102' y='183.949'/>
+<use x='120.838' xlink:href='#g2-114' y='183.949'/>
+<use x='123.73' xlink:href='#g2-97' y='183.949'/>
+<use x='127.798' xlink:href='#g2-99' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 41.401 33.989)'>
+<use x='114.487' xlink:href='#g2-101' y='183.949'/>
+<use x='118.25' xlink:href='#g2-115' y='183.949'/>
+<use x='121.497' xlink:href='#g2-112' y='183.949'/>
+<use x='125.634' xlink:href='#g2-114' y='183.949'/>
+<use x='128.526' xlink:href='#g2-101' y='183.949'/>
+<use x='132.29' xlink:href='#g2-115' y='183.949'/>
+<use x='135.536' xlink:href='#g2-115' y='183.949'/>
+<use x='138.782' xlink:href='#g2-111' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 103.095 33.989)'>
+<use x='114.487' xlink:href='#g2-98' y='183.949'/>
+<use x='118.859' xlink:href='#g2-97' y='183.949'/>
+<use x='122.692' xlink:href='#g2-114' y='183.949'/>
+<use x='125.584' xlink:href='#g2-110' y='183.949'/>
+<use x='129.957' xlink:href='#g2-101' y='183.949'/>
+<use x='133.72' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 162.903 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-101' y='183.949'/>
+<use x='120.271' xlink:href='#g2-97' y='183.949'/>
+<use x='124.339' xlink:href='#g2-110' y='183.949'/>
+<use x='128.711' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 223.526 33.989)'>
+<use x='114.487' xlink:href='#g2-114' y='183.949'/>
+<use x='117.379' xlink:href='#g2-101' y='183.949'/>
+<use x='121.142' xlink:href='#g2-100' y='183.949'/>
+<use x='125.515' xlink:href='#g2-105' y='183.949'/>
+<use x='127.535' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 277.054 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-97' y='183.949'/>
+<use x='120.34' xlink:href='#g2-114' y='183.949'/>
+<use x='123.232' xlink:href='#g2-115' y='183.949'/>
+<use x='126.478' xlink:href='#g2-111' y='183.949'/>
+<use x='130.712' xlink:href='#g2-110' y='183.949'/>
+<use x='135.085' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 21.624)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.688)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.999)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -72.311)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.622)'>
+<use x='114.487' xlink:href='#g1-50' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<path clip-path='url(#clip1)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M91.559 203.937H94.797V141.316H91.559ZM150.227 203.937H153.465V141.316H150.227ZM208.899 203.937H212.133V141.316H208.899ZM267.567 203.937H270.805V141.316H267.567ZM326.234 203.937H329.473V141.316H326.234ZM384.902 203.937H388.141V141.316H384.902Z' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M91.559 203.937H94.797V141.316H91.559ZM150.227 203.937H153.465V141.316H150.227ZM208.899 203.937H212.133V141.316H208.899ZM267.567 203.937H270.805V141.316H267.567ZM326.234 203.937H329.473V141.316H326.234ZM384.902 203.937H388.141V141.316H384.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M93.18 141.316V141.191' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M93.18 141.316V141.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M91.184 141.191H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M93.18 141.316V141.441' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M93.18 141.316V141.441' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M95.172 141.442H91.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M151.848 141.316V141.316' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M149.855 141.316H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M151.848 141.316V141.316' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M149.855 141.316H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M210.516 141.316V141.004' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M210.516 141.316V141.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M208.523 141.004H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M210.516 141.316V141.629' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M210.516 141.316V141.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M212.508 141.629H208.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M269.184 141.316V141.066' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M269.184 141.316V141.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M267.191 141.067H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M269.184 141.316V141.566' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M269.184 141.316V141.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M271.179 141.567H267.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M327.856 141.316V140.625' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M327.856 141.316V140.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M325.859 140.625H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M327.856 141.316V142.004' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M327.856 141.316V142.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M329.847 142.004H325.863' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M386.524 141.316V141.004' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M386.524 141.316V141.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M384.531 141.004H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M386.524 141.316V141.629' fill='#e0e0f0'/>
+<path clip-path='url(#clip1)' d='M386.524 141.316V141.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M388.515 141.629H384.531' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M96.789 203.937H100.027V138.937H96.789ZM155.457 203.937H158.695V139.312H155.457ZM214.129 203.937H217.363V141.004H214.129ZM272.797 203.937H276.035V136.179H272.797ZM331.465 203.937H334.703V136.617H331.465ZM390.133 203.937H393.371V78.691H390.133Z' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M96.789 203.937H100.027V138.937H96.789ZM155.457 203.937H158.695V139.312H155.457ZM214.129 203.937H217.363V141.004H214.129ZM272.797 203.937H276.035V136.179H272.797ZM331.465 203.937H334.703V136.617H331.465ZM390.133 203.937H393.371V78.691H390.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M98.41 138.937V138.683' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M98.41 138.937V138.683' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M96.414 138.683H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M98.41 138.937V139.187' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M98.41 138.937V139.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M100.402 139.187H96.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M157.078 139.312V139.312' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M155.086 139.312H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M157.078 139.312V139.312' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M155.086 139.312H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M215.746 141.004V140.625' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M215.746 141.004V140.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M213.754 140.625H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M215.746 141.004V141.379' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M215.746 141.004V141.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M217.739 141.379H213.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M274.414 136.179V135.992' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M274.414 136.179V135.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M272.422 135.992H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M274.414 136.179V136.367' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M274.414 136.179V136.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M276.41 136.367H272.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M333.086 136.617V136.429' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M333.086 136.617V136.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M331.09 136.43H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M333.086 136.617V136.804' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M333.086 136.617V136.804' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M335.078 136.804H331.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M391.754 78.691V78.691' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M389.762 78.691H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M391.754 78.691V78.691' fill='#c2c2e1'/>
+<path clip-path='url(#clip1)' d='M389.762 78.691H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M102.02 203.937H105.258V138.433H102.02ZM160.688 203.937H163.926V136.742H160.688ZM219.359 203.937H222.594V141.004H219.359ZM278.027 203.937H281.266V137.933H278.027ZM336.695 203.937H339.934V132.234H336.695ZM395.363 203.937H398.602V78.691H395.363Z' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M102.02 203.937H105.258V138.433H102.02ZM160.688 203.937H163.926V136.742H160.688ZM219.359 203.937H222.594V141.004H219.359ZM278.027 203.937H281.266V137.933H278.027ZM336.695 203.937H339.934V132.234H336.695ZM395.363 203.937H398.602V78.691H395.363Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M103.641 138.433V138.121' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M103.641 138.433V138.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M101.644 138.122H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M103.641 138.433V138.746' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M103.641 138.433V138.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M105.633 138.746H101.648' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M162.309 136.742V135.867' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M162.309 136.742V135.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M160.316 135.867H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M162.309 136.742V137.621' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M162.309 136.742V137.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M164.301 137.622H160.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M220.977 141.004V140.562' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M220.977 141.004V140.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M218.984 140.563H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M220.977 141.004V141.441' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M220.977 141.004V141.441' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M222.969 141.442H218.984' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M279.645 137.933V137.496' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M279.645 137.933V137.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M277.652 137.496H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M279.645 137.933V138.371' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M279.645 137.933V138.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M281.64 138.371H277.652' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M338.317 132.234V131.859' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M338.317 132.234V131.859' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M336.32 131.859H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M338.317 132.234V132.609' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M338.317 132.234V132.609' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M340.308 132.61H336.324' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M396.984 78.691V78.691' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M394.992 78.691H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M396.984 78.691V78.691' fill='#a3a3d1'/>
+<path clip-path='url(#clip1)' d='M394.992 78.691H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M107.25 203.937H110.488V130.48H107.25ZM165.918 203.937H169.156V133.238H165.918ZM224.59 203.937H227.824V141.254H224.59ZM283.258 203.937H286.496V137.308H283.258ZM341.926 203.937H345.164V135.742H341.926ZM400.594 203.937H403.832V78.691H400.594Z' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M107.25 203.937H110.488V130.48H107.25ZM165.918 203.937H169.156V133.238H165.918ZM224.59 203.937H227.824V141.254H224.59ZM283.258 203.937H286.496V137.308H283.258ZM341.926 203.937H345.164V135.742H341.926ZM400.594 203.937H403.832V78.691H400.594Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M108.871 130.48V130.168' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M108.871 130.48V130.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M106.875 130.168H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M108.871 130.48V130.793' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M108.871 130.48V130.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M110.864 130.793H106.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M167.539 133.238V133.238' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M165.547 133.238H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M167.539 133.238V133.238' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M165.547 133.238H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M226.207 141.254V140.75' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M226.207 141.254V140.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M224.215 140.75H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M226.207 141.254V141.754' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M226.207 141.254V141.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M228.2 141.754H224.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M284.875 137.308V136.933' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M284.875 137.308V136.933' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M282.883 136.934H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M284.875 137.308V137.683' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M284.875 137.308V137.683' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M286.868 137.683H282.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M343.547 135.742V135.617' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M343.547 135.742V135.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M341.551 135.618H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M343.547 135.742V135.867' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M343.547 135.742V135.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M345.539 135.867H341.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M402.215 78.691V78.691' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M400.223 78.691H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M402.215 78.691V78.691' fill='#8585c2'/>
+<path clip-path='url(#clip1)' d='M400.223 78.691H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M112.481 203.937H115.719V137.871H112.481ZM171.149 203.937H174.387V133.238H171.149ZM229.82 203.937H233.055V141.254H229.82ZM288.488 203.937H291.727V132.797H288.488ZM347.156 203.937H350.395V136.554H347.156ZM405.824 203.937H409.063V103.742H405.824Z' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M112.481 203.937H115.719V137.871H112.481ZM171.149 203.937H174.387V133.238H171.149ZM229.82 203.937H233.055V141.254H229.82ZM288.488 203.937H291.727V132.797H288.488ZM347.156 203.937H350.395V136.554H347.156ZM405.824 203.937H409.063V103.742H405.824Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M114.098 137.871V137.683' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M114.098 137.871V137.683' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M112.105 137.683H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M114.098 137.871V138.058' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M114.098 137.871V138.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M116.094 138.059H112.109' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M172.77 133.238V133.238' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M170.777 133.238H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M172.77 133.238V133.238' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M170.777 133.238H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M231.438 141.254V141.129' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M231.438 141.254V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M229.445 141.128H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M231.438 141.254V141.379' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M231.438 141.254V141.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M233.43 141.379H229.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M290.106 132.797V132.547' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M290.106 132.797V132.547' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M288.113 132.547H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M290.106 132.797V133.051' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M290.106 132.797V133.051' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M292.098 133.051H288.113' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M348.777 136.554V134.992' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M348.777 136.554V134.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M346.781 134.992H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M348.777 136.554V138.121' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M348.777 136.554V138.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M350.769 138.122H346.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M407.445 103.742V102.363' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M407.445 103.742V102.363' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M405.453 102.364H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M407.445 103.742V105.121' fill='#6666b3'/>
+<path clip-path='url(#clip1)' d='M407.445 103.742V105.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M409.437 105.121H405.453' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M117.711 203.937H120.949V135.867H117.711ZM176.379 203.937H179.617V134.238H176.379ZM235.051 203.937H238.285V140.941H235.051ZM293.719 203.937H296.957V132.734H293.719ZM352.387 203.937H355.625V116.203H352.387ZM411.055 203.937H414.293V84.39H411.055Z' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M117.711 203.937H120.949V135.867H117.711ZM176.379 203.937H179.617V134.238H176.379ZM235.051 203.937H238.285V140.941H235.051ZM293.719 203.937H296.957V132.734H293.719ZM352.387 203.937H355.625V116.203H352.387ZM411.055 203.937H414.293V84.39H411.055Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M119.328 135.867V135.554' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M119.328 135.867V135.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M117.336 135.555H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M119.328 135.867V136.179' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M119.328 135.867V136.179' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M121.325 136.179H117.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M178 134.238V133.238' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M178 134.238V133.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M176.008 133.238H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M178 134.238V135.242' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M178 134.238V135.242' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M179.993 135.242H176.008' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M236.668 140.941V140.687' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M236.668 140.941V140.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M234.676 140.687H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M236.668 140.941V141.191' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M236.668 140.941V141.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M238.66 141.191H234.675' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M295.336 132.734V132.609' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M295.336 132.734V132.609' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M293.344 132.61H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M295.336 132.734V132.859' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M295.336 132.734V132.859' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M297.328 132.859H293.343' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M354.008 116.203V115.39' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M354.008 116.203V115.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M352.012 115.39H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M354.008 116.203V117.015' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M354.008 116.203V117.015' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M355.999 117.016H352.015' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M412.676 84.39V83.89' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M412.676 84.39V83.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M410.684 83.891H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M412.676 84.39V84.89' fill='#4747a4'/>
+<path clip-path='url(#clip1)' d='M412.676 84.39V84.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M414.667 84.891H410.683' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M122.941 203.937H126.18V138.183H122.941ZM181.609 203.937H184.848V133.238H181.609ZM240.281 203.937H243.516V140.312H240.281ZM298.949 203.937H302.188V132.422H298.949ZM357.617 203.937H360.856V135.179H357.617ZM416.285 203.937H419.524V102.675H416.285Z' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M122.941 203.937H126.18V138.183H122.941ZM181.609 203.937H184.848V133.238H181.609ZM240.281 203.937H243.516V140.312H240.281ZM298.949 203.937H302.188V132.422H298.949ZM357.617 203.937H360.856V135.179H357.617ZM416.285 203.937H419.524V102.675H416.285Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M124.559 138.183V137.996' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M124.559 138.183V137.996' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M122.566 137.996H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M124.559 138.183V138.371' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M124.559 138.183V138.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M126.555 138.371H122.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M183.231 133.238V133.238' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M181.238 133.238H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M183.231 133.238V133.238' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M181.238 133.238H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M241.899 140.312V138.871' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M241.899 140.312V138.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M239.906 138.871H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M241.899 140.312V141.754' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M241.899 140.312V141.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M243.891 141.754H239.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M300.567 132.422V132.109' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M300.567 132.422V132.109' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M298.574 132.11H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M300.567 132.422V132.734' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M300.567 132.422V132.734' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M302.559 132.734H298.574' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M359.238 135.179V134.801' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M359.238 135.179V134.801' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M357.242 134.8H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M359.238 135.179V135.554' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M359.238 135.179V135.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M361.23 135.555H357.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M417.906 102.675V102.55' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M417.906 102.675V102.55' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M415.914 102.551H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M417.906 102.675V102.8' fill='#292994'/>
+<path clip-path='url(#clip1)' d='M417.906 102.675V102.8' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M419.898 102.801H415.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M128.172 203.937H131.41V123.969H128.172ZM186.84 203.937H190.078V127.851H186.84ZM245.512 203.937H248.746V141.504H245.512ZM304.18 203.937H307.418V137.746H304.18ZM362.848 203.937H366.086V104.492H362.848ZM421.516 203.937H424.754V78.691H421.516Z' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M128.172 203.937H131.41V123.969H128.172ZM186.84 203.937H190.078V127.851H186.84ZM245.512 203.937H248.746V141.504H245.512ZM304.18 203.937H307.418V137.746H304.18ZM362.848 203.937H366.086V104.492H362.848ZM421.516 203.937H424.754V78.691H421.516Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M129.789 123.969V123.781' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M129.789 123.969V123.781' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M127.797 123.781H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M129.789 123.969V124.156' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M129.789 123.969V124.156' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M131.785 124.157H127.8' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M188.461 127.851V126.91' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M188.461 127.851V126.91' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M186.469 126.91H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M188.461 127.851V128.789' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M188.461 127.851V128.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M190.453 128.789H186.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M247.129 141.504V141.254' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M247.129 141.504V141.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M245.137 141.254H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M247.129 141.504V141.754' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M247.129 141.504V141.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M249.121 141.754H245.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M305.797 137.746V137.558' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M305.797 137.746V137.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M303.804 137.559H307.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M305.797 137.746V137.933' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M305.797 137.746V137.933' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M307.789 137.934H303.804' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M364.469 104.492V103.742' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M364.469 104.492V103.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M362.473 103.742H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M364.469 104.492V105.246' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M364.469 104.492V105.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M366.46 105.246H362.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M423.137 78.691V78.691' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M421.144 78.691H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip1)' d='M423.137 78.691V78.691' fill='#0a0a85'/>
+<path clip-path='url(#clip1)' d='M421.144 78.691H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -89.137 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.468 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.201 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.87 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.539 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.208 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.906 247.398)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.237 247.774)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.432 249.464)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.101 244.642)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.77 245.081)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.439 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-56' y='183.949'/>
+<use x='126.877' xlink:href='#g1-52' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.676 246.897)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -20.007 245.206)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 38.662 249.464)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.331 246.396)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 156 240.697)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 214.669 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-51' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-49' y='183.949'/>
+<use x='126.877' xlink:href='#g1-52' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -73.445 238.944)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.776 241.699)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 43.893 249.715)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 102.562 245.77)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.231 244.204)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 219.9 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-48' y='183.949'/>
+<use x='126.877' xlink:href='#g1-55' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -68.215 246.333)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.546 241.699)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.123 249.715)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 107.792 241.261)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.461 245.018)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.13 212.204)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-54' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.984 244.329)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -4.315 242.701)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.354 249.402)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.023 241.198)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 171.692 224.666)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.361 192.853)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.754 246.646)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.915 241.699)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.584 248.776)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.253 240.885)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.922 243.64)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.591 211.139)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-54' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.524 232.431)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.145 236.314)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.814 249.965)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.483 246.208)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.152 212.955)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.821 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-49' y='183.949'/>
+<use x='126.877' xlink:href='#g1-49' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -124.589 311.062)'>
+<use x='114.487' xlink:href='#g0-82' y='183.949'/>
+<use x='120.457' xlink:href='#g0-101' y='183.949'/>
+<use x='124.553' xlink:href='#g0-108' y='183.949'/>
+<use x='126.753' xlink:href='#g0-97' y='183.949'/>
+<use x='131.181' xlink:href='#g0-116' y='183.949'/>
+<use x='134.509' xlink:href='#g0-105' y='183.949'/>
+<use x='136.709' xlink:href='#g0-118' y='183.949'/>
+<use x='140.957' xlink:href='#g0-101' y='183.949'/>
+<use x='148.124' xlink:href='#g0-116' y='183.949'/>
+<use x='151.452' xlink:href='#g0-105' y='183.949'/>
+<use x='153.652' xlink:href='#g0-109' y='183.949'/>
+<use x='160.972' xlink:href='#g0-101' y='183.949'/>
+<use x='168.139' xlink:href='#g2-40' y='183.949'/>
+<use x='171.432' xlink:href='#g2-108' y='183.949'/>
+<use x='173.453' xlink:href='#g2-111' y='183.949'/>
+<use x='177.452' xlink:href='#g2-119' y='183.949'/>
+<use x='183' xlink:href='#g2-101' y='183.949'/>
+<use x='186.764' xlink:href='#g2-114' y='183.949'/>
+<use x='192.479' xlink:href='#g2-105' y='183.949'/>
+<use x='194.499' xlink:href='#g2-115' y='183.949'/>
+<use x='200.568' xlink:href='#g2-98' y='183.949'/>
+<use x='205.176' xlink:href='#g2-101' y='183.949'/>
+<use x='208.94' xlink:href='#g2-116' y='183.949'/>
+<use x='211.998' xlink:href='#g2-116' y='183.949'/>
+<use x='215.056' xlink:href='#g2-101' y='183.949'/>
+<use x='218.819' xlink:href='#g2-114' y='183.949'/>
+<use x='221.711' xlink:href='#g2-41' y='183.949'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg
new file mode 100644 (file)
index 0000000..b8a2f20
--- /dev/null
@@ -0,0 +1,868 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='165.084pt' version='1.1' viewBox='52.938 54.996 381.624 165.084' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip5'>
+<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+</defs>
+<g id='page5'>
+<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' xlink:href='#g3-99' y='183.381'/>
+<use x='118.25' xlink:href='#g3-102' y='183.381'/>
+<use x='120.838' xlink:href='#g3-114' y='183.381'/>
+<use x='123.73' xlink:href='#g3-97' y='183.381'/>
+<use x='127.798' xlink:href='#g3-99' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='183.381'/>
+<use x='116.507' xlink:href='#g3-101' y='183.381'/>
+<use x='120.271' xlink:href='#g3-97' y='183.381'/>
+<use x='124.339' xlink:href='#g3-110' y='183.381'/>
+<use x='128.711' xlink:href='#g3-78' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='183.381'/>
+<use x='117.379' xlink:href='#g3-101' y='183.381'/>
+<use x='121.142' xlink:href='#g3-100' y='183.381'/>
+<use x='125.515' xlink:href='#g3-105' y='183.381'/>
+<use x='127.535' xlink:href='#g3-115' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' xlink:href='#g3-108' y='183.381'/>
+<use x='116.507' xlink:href='#g3-97' y='183.381'/>
+<use x='120.34' xlink:href='#g3-114' y='183.381'/>
+<use x='123.232' xlink:href='#g3-115' y='183.381'/>
+<use x='126.478' xlink:href='#g3-111' y='183.381'/>
+<use x='130.712' xlink:href='#g3-110' y='183.381'/>
+<use x='135.085' xlink:href='#g3-78' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' xlink:href='#g3-109' y='183.381'/>
+<use x='121.211' xlink:href='#g3-115' y='183.381'/>
+<use x='124.458' xlink:href='#g3-116' y='183.381'/>
+<use x='127.516' xlink:href='#g3-114' y='183.381'/>
+<use x='130.408' xlink:href='#g3-101' y='183.381'/>
+<use x='134.171' xlink:href='#g3-115' y='183.381'/>
+<use x='137.418' xlink:href='#g3-115' y='183.381'/>
+<use x='140.664' xlink:href='#g3-78' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' xlink:href='#g3-114' y='183.381'/>
+<use x='117.379' xlink:href='#g3-112' y='183.381'/>
+<use x='121.751' xlink:href='#g3-116' y='183.381'/>
+<use x='124.809' xlink:href='#g3-101' y='183.381'/>
+<use x='128.573' xlink:href='#g3-115' y='183.381'/>
+<use x='131.819' xlink:href='#g3-116' y='183.381'/>
+<use x='134.877' xlink:href='#g3-78' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' xlink:href='#g2-48' y='183.381'/>
+<use x='117.133' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
+<use x='114.487' xlink:href='#g2-48' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
+<use x='114.487' xlink:href='#g2-50' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-120' y='183.381'/>
+</g>
+<path clip-path='url(#clip5)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M88.945 203.937H92.18V141.316H88.945ZM147.613 203.937H150.852V141.316H147.613ZM206.281 203.937H209.52V141.316H206.281ZM264.949 203.937H268.188V141.316H264.949ZM323.621 203.937H326.859V141.316H323.621ZM382.289 203.937H385.527V141.316H382.289Z' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M88.945 203.937H92.18V141.316H88.945ZM147.613 203.937H150.852V141.316H147.613ZM206.281 203.937H209.52V141.316H206.281ZM264.949 203.937H268.188V141.316H264.949ZM323.621 203.937H326.859V141.316H323.621ZM382.289 203.937H385.527V141.316H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M90.563 141.316V141.129' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M90.563 141.316V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M88.57 141.129H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M90.563 141.316V141.504' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M90.563 141.316V141.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M92.555 141.504H88.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M149.231 141.316V140.937' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M149.231 141.316V140.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M147.238 140.937H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M149.231 141.316V141.691' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M149.231 141.316V141.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M151.223 141.692H147.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M207.902 141.316V139.562' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M207.902 141.316V139.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M205.906 139.563H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M207.902 141.316V143.07' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M207.902 141.316V143.07' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M209.895 143.071H205.91' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M266.57 141.316V140.25' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M266.57 141.316V140.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M264.578 140.25H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M266.57 141.316V142.379' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M266.57 141.316V142.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M268.562 142.379H264.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M325.238 141.316V139.312' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M325.238 141.316V139.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M323.246 139.312H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M325.238 141.316V143.32' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M325.238 141.316V143.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M327.231 143.32H323.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M383.906 141.316V139.875' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M383.906 141.316V139.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M381.914 139.875H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M383.906 141.316V142.754' fill='#993333'/>
+<path clip-path='url(#clip5)' d='M383.906 141.316V142.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M385.902 142.753H381.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M94.176 203.937H97.41V140.875H94.176ZM152.844 203.937H156.082V135.617H152.844ZM211.512 203.937H214.75V136.805H211.512ZM270.18 203.937H273.418V78.691H270.18ZM328.852 203.937H332.09V139.625H328.852ZM387.52 203.937H390.758V105.746H387.52Z' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M94.176 203.937H97.41V140.875H94.176ZM152.844 203.937H156.082V135.617H152.844ZM211.512 203.937H214.75V136.805H211.512ZM270.18 203.937H273.418V78.691H270.18ZM328.852 203.937H332.09V139.625H328.852ZM387.52 203.937H390.758V105.746H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M95.793 140.875V140.625' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M95.793 140.875V140.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M93.801 140.625H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M95.793 140.875V141.129' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M95.793 140.875V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M97.785 141.129H93.801' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M154.461 135.617V135.242' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M154.461 135.617V135.242' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M152.469 135.242H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M154.461 135.617V135.992' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M154.461 135.617V135.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M156.453 135.992H152.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M213.133 136.805V135.68' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M213.133 136.805V135.68' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M211.137 135.68H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M213.133 136.805V137.934' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M213.133 136.805V137.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M215.125 137.934H211.14' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M271.801 78.691V78.691' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M269.809 78.691H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M271.801 78.691V78.691' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M269.809 78.691H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M330.469 139.625V139.312' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M330.469 139.625V139.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M328.477 139.312H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M330.469 139.625V139.937' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M330.469 139.625V139.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M332.461 139.937H328.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M389.137 105.746V99.609' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M389.137 105.746V99.609' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M387.145 99.609H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M389.137 105.746V111.883' fill='#8080bf'/>
+<path clip-path='url(#clip5)' d='M389.137 105.746V111.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M391.132 111.883H387.144' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M99.406 203.937H102.641V139.437H99.406ZM158.074 203.937H161.313V140.437H158.074ZM216.742 203.937H219.981V132.922H216.742ZM275.41 203.937H278.649V78.691H275.41ZM334.082 203.937H337.32V106.996H334.082ZM392.75 203.937H395.988V78.691H392.75Z' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M99.406 203.937H102.641V139.437H99.406ZM158.074 203.937H161.313V140.437H158.074ZM216.742 203.937H219.981V132.922H216.742ZM275.41 203.937H278.649V78.691H275.41ZM334.082 203.937H337.32V106.996H334.082ZM392.75 203.937H395.988V78.691H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M101.024 139.437V139.25' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M101.024 139.437V139.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M99.031 139.25H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M101.024 139.437V139.625' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M101.024 139.437V139.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M103.016 139.625H99.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M159.691 140.437V140.062' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M159.691 140.437V140.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M157.699 140.063H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M159.691 140.437V140.812' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M159.691 140.437V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M161.684 140.812H157.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M218.363 132.922V131.547' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M218.363 132.922V131.547' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M216.367 131.547H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M218.363 132.922V134.301' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M218.363 132.922V134.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M220.356 134.3H216.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M277.031 78.691V78.691' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M275.039 78.691H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M277.031 78.691V78.691' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M275.039 78.691H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M335.699 106.996V105.621' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M335.699 106.996V105.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M333.707 105.621H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M335.699 106.996V108.375' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M335.699 106.996V108.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M337.692 108.375H333.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M394.367 78.691V78.691' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M392.375 78.691H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M394.367 78.691V78.691' fill='#ffb733'/>
+<path clip-path='url(#clip5)' d='M392.375 78.691H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M104.637 203.937H107.871V124.344H104.637ZM163.305 203.937H166.543V135.742H163.305ZM221.973 203.937H225.211V105.996H221.973ZM280.641 203.937H283.879V98.168H280.641ZM339.313 203.937H342.551V122.715H339.313ZM397.981 203.937H401.219V120.336H397.981Z' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M104.637 203.937H107.871V124.344H104.637ZM163.305 203.937H166.543V135.742H163.305ZM221.973 203.937H225.211V105.996H221.973ZM280.641 203.937H283.879V98.168H280.641ZM339.313 203.937H342.551V122.715H339.313ZM397.981 203.937H401.219V120.336H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M106.254 124.344V124.031' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M106.254 124.344V124.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M104.261 124.031H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M106.254 124.344V124.656' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M106.254 124.344V124.656' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M108.246 124.656H104.261' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M164.922 135.742V135.555' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M164.922 135.742V135.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M162.929 135.555H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M164.922 135.742V135.93' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M164.922 135.742V135.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M166.914 135.93H162.929' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M223.594 105.996V104.805' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M223.594 105.996V104.805' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M221.597 104.805H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M223.594 105.996V107.187' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M223.594 105.996V107.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M225.586 107.188H221.601' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M282.262 98.168V96.289' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M282.262 98.168V96.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M280.269 96.289H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M282.262 98.168V100.047' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M282.262 98.168V100.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M284.254 100.047H280.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M340.93 122.715V121.527' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M340.93 122.715V121.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M338.937 121.527H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M340.93 122.715V123.906' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M340.93 122.715V123.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M342.922 123.906H338.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M399.598 120.336V114.137' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M399.598 120.336V114.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M397.605 114.137H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M399.598 120.336V126.535' fill='#bf80bf'/>
+<path clip-path='url(#clip5)' d='M399.598 120.336V126.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M401.593 126.535H397.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M109.867 203.937H113.102V140.687H109.867ZM168.535 203.937H171.774V141.316H168.535ZM227.203 203.937H230.442V140.625H227.203ZM285.871 203.937H289.109V136.555H285.871ZM344.543 203.937H347.781V115.453H344.543ZM403.211 203.937H406.449V135.242H403.211Z' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M109.867 203.937H113.102V140.687H109.867ZM168.535 203.937H171.774V141.316H168.535ZM227.203 203.937H230.442V140.625H227.203ZM285.871 203.937H289.109V136.555H285.871ZM344.543 203.937H347.781V115.453H344.543ZM403.211 203.937H406.449V135.242H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M111.484 140.687V140.562' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M111.484 140.687V140.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M109.492 140.563H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M111.484 140.687V140.812' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M111.484 140.687V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M113.477 140.812H109.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M170.152 141.316V140.937' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M170.152 141.316V140.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M168.16 140.937H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M170.152 141.316V141.691' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M170.152 141.316V141.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M172.145 141.692H168.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M228.824 140.625V139.25' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M228.824 140.625V139.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M226.828 139.25H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M228.824 140.625V142.004' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M228.824 140.625V142.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M230.817 142.004H226.832' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M287.492 136.555V134.801' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M287.492 136.555V134.801' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M285.5 134.8H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M287.492 136.555V138.309' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M287.492 136.555V138.309' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M289.485 138.308H285.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M346.16 115.453V114.074' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M346.16 115.453V114.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M344.168 114.074H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M346.16 115.453V116.828' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M346.16 115.453V116.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M348.153 116.829H344.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M404.828 135.242V128.539' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M404.828 135.242V128.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M402.836 128.539H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M404.828 135.242V141.941' fill='#dfbf9f'/>
+<path clip-path='url(#clip5)' d='M404.828 135.242V141.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M406.824 141.941H402.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M115.098 203.937H118.332V136.055H115.098ZM173.766 203.937H177.004V128.539H173.766ZM232.434 203.937H235.672V116.016H232.434ZM291.102 203.937H294.34V78.691H291.102ZM349.774 203.937H353.012V78.691H349.774ZM408.442 203.937H411.68V78.691H408.442Z' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M115.098 203.937H118.332V136.055H115.098ZM173.766 203.937H177.004V128.539H173.766ZM232.434 203.937H235.672V116.016H232.434ZM291.102 203.937H294.34V78.691H291.102ZM349.774 203.937H353.012V78.691H349.774ZM408.442 203.937H411.68V78.691H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M116.715 136.055V135.93' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M116.715 136.055V135.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M114.722 135.93H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M116.715 136.055V136.18' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M116.715 136.055V136.18' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M118.707 136.18H114.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M175.383 128.539V126.723' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M175.383 128.539V126.723' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M173.39 126.723H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M175.383 128.539V130.355' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M175.383 128.539V130.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M177.375 130.355H173.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M234.055 116.016V114.449' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M234.055 116.016V114.449' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M232.058 114.449H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M234.055 116.016V117.582' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M234.055 116.016V117.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M236.047 117.582H232.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M292.723 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M290.73 78.691H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M292.723 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M290.73 78.691H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M351.391 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M349.398 78.691H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M351.391 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M349.398 78.691H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M410.059 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M408.066 78.691H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M410.059 78.691V78.691' fill='#80bf80'/>
+<path clip-path='url(#clip5)' d='M408.066 78.691H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M120.328 203.937H123.563V137.621H120.328ZM178.996 203.937H182.234V197.676H178.996ZM237.664 203.937H240.902V136.43H237.664ZM296.332 203.937H299.57V116.953H296.332ZM355.004 203.937H358.238V197.676H355.004ZM413.672 203.937H416.91V78.691H413.672Z' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M120.328 203.937H123.563V137.621H120.328ZM178.996 203.937H182.234V197.676H178.996ZM237.664 203.937H240.902V136.43H237.664ZM296.332 203.937H299.57V116.953H296.332ZM355.004 203.937H358.238V197.676H355.004ZM413.672 203.937H416.91V78.691H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M121.945 137.621V137.371' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M121.945 137.621V137.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M119.953 137.371H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M121.945 137.621V137.871' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M121.945 137.621V137.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M123.938 137.871H119.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M180.613 197.676V197.676' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M178.621 197.676H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M180.613 197.676V197.676' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M178.621 197.676H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M239.285 136.43V134.988' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M239.285 136.43V134.988' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M237.289 134.988H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M239.285 136.43V137.871' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M239.285 136.43V137.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M241.278 137.871H237.293' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M297.953 116.953V115.391' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M297.953 116.953V115.391' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M295.961 115.39H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M297.953 116.953V118.519' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M297.953 116.953V118.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M299.946 118.519H295.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M356.621 197.676V197.676' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M354.629 197.676H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M356.621 197.676V197.676' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M354.629 197.676H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M415.289 78.691V78.691' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M413.297 78.691H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M415.289 78.691V78.691' fill='#bfbf80'/>
+<path clip-path='url(#clip5)' d='M413.297 78.691H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M125.559 203.937H128.793V138.121H125.559ZM184.227 203.937H187.465V132.047H184.227ZM242.895 203.937H246.133V134.426H242.895ZM301.563 203.937H304.801V78.691H301.563ZM360.234 203.937H363.469V78.691H360.234ZM418.902 203.937H422.141V109.254H418.902Z' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M125.559 203.937H128.793V138.121H125.559ZM184.227 203.937H187.465V132.047H184.227ZM242.895 203.937H246.133V134.426H242.895ZM301.563 203.937H304.801V78.691H301.563ZM360.234 203.937H363.469V78.691H360.234ZM418.902 203.937H422.141V109.254H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M127.176 138.121V137.934' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M127.176 138.121V137.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M125.183 137.934H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M127.176 138.121V138.309' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M127.176 138.121V138.309' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M129.168 138.308H125.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M185.844 132.047V131.672' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M185.844 132.047V131.672' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M183.851 131.672H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M185.844 132.047V132.422' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M185.844 132.047V132.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M187.836 132.422H183.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M244.516 134.426V133.488' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M244.516 134.426V133.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M242.519 133.488H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M244.516 134.426V135.367' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M244.516 134.426V135.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M246.508 135.367H242.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M303.184 78.691V78.691' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M301.191 78.691H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M303.184 78.691V78.691' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M301.191 78.691H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M361.852 78.691V78.691' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M359.859 78.691H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M361.852 78.691V78.691' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M359.859 78.691H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M420.52 109.254V107.25' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M420.52 109.254V107.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M418.527 107.25H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M420.52 109.254V111.258' fill='#339999'/>
+<path clip-path='url(#clip5)' d='M420.52 109.254V111.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M422.512 111.258H418.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M130.789 203.937H134.024V139.187H130.789ZM189.457 203.937H192.695V139.312H189.457ZM248.125 203.937H251.363V140.062H248.125ZM306.793 203.937H310.031V126.035H306.793ZM365.465 203.937H368.699V103.176H365.465ZM424.133 203.937H427.371V113.762H424.133Z' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M130.789 203.937H134.024V139.187H130.789ZM189.457 203.937H192.695V139.312H189.457ZM248.125 203.937H251.363V140.062H248.125ZM306.793 203.937H310.031V126.035H306.793ZM365.465 203.937H368.699V103.176H365.465ZM424.133 203.937H427.371V113.762H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M132.406 139.187V138.934' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M132.406 139.187V138.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M130.414 138.933H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M132.406 139.187V139.437' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M132.406 139.187V139.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M134.399 139.437H130.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M191.074 139.312V139.062' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M191.074 139.312V139.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M189.082 139.063H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M191.074 139.312V139.562' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M191.074 139.312V139.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M193.067 139.563H189.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M249.746 140.062V138.871' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M249.746 140.062V138.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M247.75 138.871H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M249.746 140.062V141.254' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M249.746 140.062V141.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M251.739 141.254H247.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M308.414 126.035V125.031' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M308.414 126.035V125.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M306.422 125.031H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M308.414 126.035V127.035' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M308.414 126.035V127.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M310.407 127.035H306.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M367.082 103.176V101.613' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M367.082 103.176V101.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M365.09 101.613H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M367.082 103.176V104.742' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M367.082 103.176V104.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M369.075 104.742H365.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M425.75 113.762V105.184' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M425.75 113.762V105.184' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M423.758 105.184H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M425.75 113.762V122.34' fill='#bf8080'/>
+<path clip-path='url(#clip5)' d='M425.75 113.762V122.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M427.743 122.34H423.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -91.184 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.515 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.154 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 84.823 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.492 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.161 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -85.954 249.339)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -27.284 244.079)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-57' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.385 245.269)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-55' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.054 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-52' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-57' y='183.381'/>
+<use x='126.877' xlink:href='#g2-52' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 148.723 248.087)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-51' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.392 214.208)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-55' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -80.723 247.899)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-51' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -22.054 248.901)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.615 241.386)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-49' y='183.381'/>
+<use x='121.25' xlink:href='#g2-51' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.284 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-53' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-50' y='183.381'/>
+<use x='126.877' xlink:href='#g2-50' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 153.953 215.46)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-53' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.622 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-51' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-55' y='183.381'/>
+<use x='126.877' xlink:href='#g2-56' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -75.493 232.807)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-50' y='183.381'/>
+<use x='121.25' xlink:href='#g2-55' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.824 244.204)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-57' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 41.845 214.458)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-54' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.514 206.63)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-54' y='183.381'/>
+<use x='121.25' xlink:href='#g2-57' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.183 231.178)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-51' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 217.852 228.799)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-51' y='183.381'/>
+<use x='121.25' xlink:href='#g2-52' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -70.262 249.151)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -11.593 249.777)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 47.076 249.089)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 105.745 245.018)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-56' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 164.414 223.914)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-52' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 223.083 243.703)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-49' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -65.032 244.517)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-56' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -6.363 237.002)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-50' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 52.306 224.478)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-52' y='183.381'/>
+<use x='121.25' xlink:href='#g2-48' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 110.975 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-51' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-48' y='183.381'/>
+<use x='126.877' xlink:href='#g2-50' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 169.644 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-50' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-51' y='183.381'/>
+<use x='126.877' xlink:href='#g2-49' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 228.313 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-52' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-54' y='183.381'/>
+<use x='126.877' xlink:href='#g2-51' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -59.801 246.083)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-54' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -1.66 306.138)'>
+<use x='114.487' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 57.537 244.893)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-56' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 116.206 225.417)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-51' y='183.381'/>
+<use x='121.25' xlink:href='#g2-57' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 174.347 306.138)'>
+<use x='114.487' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 233.544 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-51' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-56' y='183.381'/>
+<use x='126.877' xlink:href='#g2-53' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -54.571 246.584)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-53' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 4.098 240.509)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-49' y='183.381'/>
+<use x='121.25' xlink:href='#g2-53' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 62.767 242.889)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-49' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 121.436 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-51' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-50' y='183.381'/>
+<use x='126.877' xlink:href='#g2-50' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 180.105 187.154)'>
+<use x='109.598' xlink:href='#g4-1' y='183.381'/>
+<use x='113.103' xlink:href='#g4-1' y='183.381'/>
+<use x='116.608' xlink:href='#g4-1' y='183.381'/>
+<use x='120.114' xlink:href='#g2-50' y='183.381'/>
+<use x='122.76' xlink:href='#g2-46' y='183.381'/>
+<use x='124.23' xlink:href='#g2-56' y='183.381'/>
+<use x='126.877' xlink:href='#g2-56' y='183.381'/>
+<use x='129.523' xlink:href='#g2-120' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 238.774 217.714)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-53' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -49.34 247.648)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-51' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 9.329 247.773)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-51' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 67.998 248.525)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-48' y='183.381'/>
+<use x='121.25' xlink:href='#g2-50' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 126.667 234.497)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-50' y='183.381'/>
+<use x='121.25' xlink:href='#g2-52' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 185.336 211.64)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-54' y='183.381'/>
+<use x='121.25' xlink:href='#g2-49' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 244.005 222.223)'>
+<use x='114.487' xlink:href='#g2-49' y='183.381'/>
+<use x='117.133' xlink:href='#g2-46' y='183.381'/>
+<use x='118.603' xlink:href='#g2-52' y='183.381'/>
+<use x='121.25' xlink:href='#g2-52' y='183.381'/>
+</g>
+<g transform='matrix(0 -1 1 0 -124.021 311.062)'>
+<use x='114.487' xlink:href='#g1-82' y='183.381'/>
+<use x='120.457' xlink:href='#g1-101' y='183.381'/>
+<use x='124.553' xlink:href='#g1-108' y='183.381'/>
+<use x='126.753' xlink:href='#g1-97' y='183.381'/>
+<use x='131.181' xlink:href='#g1-116' y='183.381'/>
+<use x='134.509' xlink:href='#g1-105' y='183.381'/>
+<use x='136.709' xlink:href='#g1-118' y='183.381'/>
+<use x='140.957' xlink:href='#g1-101' y='183.381'/>
+<use x='148.124' xlink:href='#g1-116' y='183.381'/>
+<use x='151.452' xlink:href='#g1-105' y='183.381'/>
+<use x='153.652' xlink:href='#g1-109' y='183.381'/>
+<use x='160.972' xlink:href='#g1-101' y='183.381'/>
+<use x='168.139' xlink:href='#g3-40' y='183.381'/>
+<use x='171.432' xlink:href='#g3-108' y='183.381'/>
+<use x='173.453' xlink:href='#g3-111' y='183.381'/>
+<use x='177.452' xlink:href='#g3-119' y='183.381'/>
+<use x='183' xlink:href='#g3-101' y='183.381'/>
+<use x='186.764' xlink:href='#g3-114' y='183.381'/>
+<use x='192.479' xlink:href='#g3-105' y='183.381'/>
+<use x='194.499' xlink:href='#g3-115' y='183.381'/>
+<use x='200.568' xlink:href='#g3-98' y='183.381'/>
+<use x='205.176' xlink:href='#g3-101' y='183.381'/>
+<use x='208.94' xlink:href='#g3-116' y='183.381'/>
+<use x='211.998' xlink:href='#g3-116' y='183.381'/>
+<use x='215.056' xlink:href='#g3-101' y='183.381'/>
+<use x='218.819' xlink:href='#g3-114' y='183.381'/>
+<use x='221.711' xlink:href='#g3-41' y='183.381'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg
new file mode 100644 (file)
index 0000000..4a7e21e
--- /dev/null
@@ -0,0 +1,1157 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='258.383pt' version='1.1' viewBox='106.736 54.996 381.623 258.383' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip6'>
+<path d='M135.949 251.93H487.961V84.164H135.949Z'/>
+</clipPath>
+<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
+<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
+<use id='g3-45' transform='scale(1.143)' xlink:href='#g0-45'/>
+<use id='g3-49' transform='scale(1.143)' xlink:href='#g0-49'/>
+<use id='g3-54' transform='scale(1.143)' xlink:href='#g0-54'/>
+<use id='g3-56' transform='scale(1.143)' xlink:href='#g0-56'/>
+<use id='g3-58' transform='scale(1.143)' xlink:href='#g0-58'/>
+<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
+<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
+<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
+<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
+<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
+<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
+<use id='g3-103' transform='scale(1.143)' xlink:href='#g0-103'/>
+<use id='g3-104' transform='scale(1.143)' xlink:href='#g0-104'/>
+<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
+<use id='g3-106' transform='scale(1.143)' xlink:href='#g0-106'/>
+<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
+<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
+<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
+<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
+<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
+<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
+<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
+<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
+<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
+<use id='g3-120' transform='scale(1.143)' xlink:href='#g0-120'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
+<use id='g2-44' transform='scale(0.714)' xlink:href='#g0-44'/>
+<use id='g2-45' transform='scale(0.714)' xlink:href='#g0-45'/>
+<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
+<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
+<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
+<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
+<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
+<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
+<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
+<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
+<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
+<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
+<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
+<use id='g2-64' transform='scale(0.714)' xlink:href='#g0-64'/>
+<use id='g2-65' transform='scale(0.714)' xlink:href='#g0-65'/>
+<use id='g2-67' transform='scale(0.714)' xlink:href='#g0-67'/>
+<use id='g2-68' transform='scale(0.714)' xlink:href='#g0-68'/>
+<use id='g2-71' transform='scale(0.714)' xlink:href='#g0-71'/>
+<use id='g2-77' transform='scale(0.714)' xlink:href='#g0-77'/>
+<use id='g2-85' transform='scale(0.714)' xlink:href='#g0-85'/>
+<use id='g2-97' transform='scale(0.714)' xlink:href='#g0-97'/>
+<use id='g2-98' transform='scale(0.714)' xlink:href='#g0-98'/>
+<use id='g2-99' transform='scale(0.714)' xlink:href='#g0-99'/>
+<use id='g2-100' transform='scale(0.714)' xlink:href='#g0-100'/>
+<use id='g2-101' transform='scale(0.714)' xlink:href='#g0-101'/>
+<use id='g2-103' transform='scale(0.714)' xlink:href='#g0-103'/>
+<use id='g2-104' transform='scale(0.714)' xlink:href='#g0-104'/>
+<use id='g2-108' transform='scale(0.714)' xlink:href='#g0-108'/>
+<use id='g2-109' transform='scale(0.714)' xlink:href='#g0-109'/>
+<use id='g2-110' transform='scale(0.714)' xlink:href='#g0-110'/>
+<use id='g2-111' transform='scale(0.714)' xlink:href='#g0-111'/>
+<use id='g2-112' transform='scale(0.714)' xlink:href='#g0-112'/>
+<use id='g2-114' transform='scale(0.714)' xlink:href='#g0-114'/>
+<use id='g2-115' transform='scale(0.714)' xlink:href='#g0-115'/>
+<use id='g2-116' transform='scale(0.714)' xlink:href='#g0-116'/>
+<use id='g2-117' transform='scale(0.714)' xlink:href='#g0-117'/>
+<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
+<use id='g2-122' transform='scale(0.714)' xlink:href='#g0-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
+<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
+<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
+<path d='M1.339 -0.007V-0.628H0.711V0H0.907L0.704 0.893H1.018L1.339 -0.007Z' id='g0-44'/>
+<path d='M2.05 -1.332V-1.771H0.084V-1.332H2.05Z' id='g0-45'/>
+<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
+<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
+<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
+<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
+<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
+<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
+<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
+<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
+<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
+<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
+<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
+<path d='M1.339 -3.096H0.711V-2.469H1.339V-3.096ZM0.711 -0.628V0H1.339V-0.628H0.711Z' id='g0-58'/>
+<path d='M4.142 -0.614C4.038 -0.614 4.024 -0.614 3.968 -0.586C3.626 -0.467 3.271 -0.391 2.901 -0.391C1.778 -0.391 0.976 -1.339 0.976 -2.42C0.976 -3.592 1.883 -4.449 2.859 -4.449C3.055 -4.449 3.515 -4.4 3.745 -3.843C3.55 -3.954 3.333 -4.003 3.152 -4.003C2.406 -4.003 1.778 -3.306 1.778 -2.42C1.778 -1.513 2.427 -0.837 3.145 -0.837C3.689 -0.837 4.519 -1.276 4.519 -2.518C4.519 -3.222 4.47 -4.91 2.866 -4.91C1.541 -4.91 0.411 -3.815 0.411 -2.42C0.411 -1.039 1.527 0.07 2.873 0.07C3.515 0.07 4.115 -0.195 4.519 -0.614H4.142ZM3.152 -1.297C2.72 -1.297 2.343 -1.778 2.343 -2.42C2.343 -3.082 2.734 -3.543 3.145 -3.543C3.578 -3.543 3.954 -3.062 3.954 -2.42C3.954 -1.757 3.564 -1.297 3.152 -1.297Z' id='g0-64'/>
+<path d='M2.803 -4.84H2.127L0.209 0H0.781L1.325 -1.381H3.445L3.989 0H4.721L2.803 -4.84ZM2.392 -4.31L3.271 -1.792H1.499L2.392 -4.31Z' id='g0-65'/>
+<path d='M4.317 -0.851C3.829 -0.551 3.605 -0.418 2.908 -0.418C1.827 -0.418 1.172 -1.43 1.172 -2.434C1.172 -3.466 1.89 -4.435 2.908 -4.435C3.368 -4.435 3.843 -4.289 4.163 -4.045L4.275 -4.679C3.787 -4.861 3.396 -4.917 2.887 -4.917C1.506 -4.917 0.474 -3.773 0.474 -2.427C0.474 -0.99 1.569 0.07 2.929 0.07C3.612 0.07 3.898 -0.07 4.359 -0.321L4.317 -0.851Z' id='g0-67'/>
+<path d='M0.683 -4.84V0H2.664C3.919 0 4.931 -1.06 4.931 -2.378C4.931 -3.745 3.912 -4.84 2.664 -4.84H0.683ZM1.367 -0.411V-4.428H2.476C3.431 -4.428 4.247 -3.668 4.247 -2.385C4.247 -1.088 3.396 -0.411 2.476 -0.411H1.367Z' id='g0-68'/>
+<path d='M4.442 -2.085H2.88V-1.625H3.829V-0.558C3.522 -0.481 3.222 -0.418 2.908 -0.418C1.834 -0.418 1.172 -1.43 1.172 -2.427C1.172 -3.382 1.82 -4.435 2.873 -4.435C3.515 -4.435 3.919 -4.24 4.268 -3.947L4.38 -4.582C3.898 -4.812 3.473 -4.924 2.943 -4.924C1.534 -4.924 0.474 -3.822 0.474 -2.427C0.474 -1.067 1.527 0.07 2.901 0.07C3.403 0.07 3.996 -0.042 4.442 -0.272V-2.085Z' id='g0-71'/>
+<path d='M3.884 -2.42C3.801 -2.211 3.299 -0.983 3.229 -0.69H3.222C3.173 -0.893 2.852 -1.695 2.783 -1.876L1.583 -4.84H0.732V0H1.318V-4.282H1.325C1.381 -4.038 1.743 -3.117 1.778 -3.041L2.943 -0.146H3.494L4.533 -2.713C4.533 -2.72 5.014 -3.905 5.133 -4.289H5.14V0H5.726V-4.84H4.868L3.884 -2.42Z' id='g0-77'/>
+<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
+<path d='M4.4 -4.84H3.794V-1.625C3.794 -0.69 3.166 -0.265 2.566 -0.265S1.381 -0.697 1.381 -1.618V-4.84H0.676V-1.632C0.676 -0.607 1.555 0.146 2.559 0.146C3.557 0.146 4.4 -0.614 4.4 -1.632V-4.84Z' id='g0-85'/>
+<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
+<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
+<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
+<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
+<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
+<path d='M3.508 -3.166C3.354 -3.166 2.887 -3.159 2.357 -2.957L2.343 -2.95C2.092 -3.117 1.848 -3.166 1.646 -3.166C0.962 -3.166 0.453 -2.629 0.453 -2.029C0.453 -1.785 0.537 -1.534 0.697 -1.339C0.6 -1.22 0.495 -1.025 0.495 -0.76C0.495 -0.488 0.607 -0.314 0.669 -0.23C0.286 -0.007 0.209 0.314 0.209 0.481C0.209 1.011 0.941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 0.481C3.487 -0.502 2.267 -0.502 1.967 -0.502H1.318C1.206 -0.502 0.907 -0.502 0.907 -0.865C0.907 -1.004 0.955 -1.074 0.962 -1.088C1.206 -0.934 1.451 -0.886 1.639 -0.886C2.322 -0.886 2.831 -1.423 2.831 -2.022C2.831 -2.246 2.769 -2.448 2.643 -2.636C2.615 -2.678 2.615 -2.685 2.615 -2.692C2.615 -2.72 3.034 -2.72 3.068 -2.72C3.075 -2.72 3.34 -2.72 3.592 -2.692L3.508 -3.166ZM1.646 -1.318C1.269 -1.318 0.99 -1.555 0.99 -2.022C0.99 -2.566 1.339 -2.734 1.639 -2.734C2.015 -2.734 2.294 -2.497 2.294 -2.029C2.294 -1.485 1.946 -1.318 1.646 -1.318ZM1.974 0.042C2.134 0.042 2.957 0.042 2.957 0.488C2.957 0.788 2.434 0.997 1.848 0.997S0.739 0.788 0.739 0.488C0.739 0.453 0.739 0.042 1.304 0.042H1.974Z' id='g0-103'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.625 -3.166 1.304 -2.817 1.165 -2.671V-4.84H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-104'/>
+<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
+<path d='M1.381 -4.784H0.676V-4.08H1.381V-4.784ZM-0.453 1.186C-0.133 1.36 0.181 1.423 0.446 1.423C0.928 1.423 1.381 1.053 1.381 0.411V-3.096H0.795V0.46C0.795 0.586 0.795 0.697 0.649 0.816C0.488 0.934 0.293 0.934 0.23 0.934C-0.063 0.934 -0.244 0.802 -0.328 0.725L-0.453 1.186Z' id='g0-106'/>
+<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
+<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
+<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
+<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
+<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
+<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
+<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
+<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
+<path d='M3.243 -3.096H2.636V-1.074C2.636 -0.516 2.162 -0.342 1.757 -0.342C1.241 -0.342 1.186 -0.481 1.186 -0.802V-3.096H0.579V-0.76C0.579 -0.139 0.851 0.07 1.339 0.07C1.625 0.07 2.239 0.014 2.657 -0.321V0H3.243V-3.096Z' id='g0-117'/>
+<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
+<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
+<path d='M2.957 -2.803V-3.096H0.307V-2.65H1.332C1.416 -2.65 1.499 -2.657 1.583 -2.657H2.127L0.209 -0.307V0H2.978V-0.467H1.897C1.813 -0.467 1.73 -0.46 1.646 -0.46H1.039L2.957 -2.803Z' id='g0-122'/>
+</defs>
+<g id='page6'>
+<path d='M194.617 260.785V251.93M253.285 260.785V251.93M311.953 260.785V251.93M370.625 260.785V251.93M429.293 260.785V251.93M194.617 75.308V84.164M253.285 75.308V84.164M311.953 75.308V84.164M370.625 75.308V84.164M429.293 75.308V84.164' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 256.18V251.93M223.953 256.18V251.93M282.621 256.18V251.93M341.289 256.18V251.93M399.957 256.18V251.93M458.629 256.18V251.93M165.281 79.91V84.164M223.953 79.91V84.164M282.621 79.91V84.164M341.289 79.91V84.164M399.957 79.91V84.164M458.629 79.91V84.164' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 251.93H140.199M135.949 218.375H140.199M135.949 184.824H140.199M135.949 151.269H140.199M135.949 117.719H140.199M135.949 84.164H140.199M487.961 251.93H483.711M487.961 218.375H483.711M487.961 184.824H483.711M487.961 151.269H483.711M487.961 117.719H483.711M487.961 84.164H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 251.93V84.164H487.961V251.93H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='191.334'/>
+<use x='172.353' xlink:href='#g3-108' y='191.334'/>
+<use x='174.373' xlink:href='#g3-108' y='191.334'/>
+<use x='176.393' xlink:href='#g3-111' y='191.334'/>
+<use x='180.863' xlink:href='#g3-99' y='191.334'/>
+<use x='184.627' xlink:href='#g3-45' y='191.334'/>
+<use x='187.449' xlink:href='#g3-116' y='191.334'/>
+<use x='190.507' xlink:href='#g3-101' y='191.334'/>
+<use x='194.271' xlink:href='#g3-115' y='191.334'/>
+<use x='197.517' xlink:href='#g3-116' y='191.334'/>
+<use x='200.575' xlink:href='#g3-49' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' xlink:href='#g3-97' y='191.334'/>
+<use x='172.353' xlink:href='#g3-108' y='191.334'/>
+<use x='174.373' xlink:href='#g3-108' y='191.334'/>
+<use x='176.393' xlink:href='#g3-111' y='191.334'/>
+<use x='180.863' xlink:href='#g3-99' y='191.334'/>
+<use x='184.627' xlink:href='#g3-45' y='191.334'/>
+<use x='187.449' xlink:href='#g3-116' y='191.334'/>
+<use x='190.507' xlink:href='#g3-101' y='191.334'/>
+<use x='194.271' xlink:href='#g3-115' y='191.334'/>
+<use x='197.517' xlink:href='#g3-116' y='191.334'/>
+<use x='200.575' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='191.334'/>
+<use x='171.531' xlink:href='#g3-104' y='191.334'/>
+<use x='175.904' xlink:href='#g3-54' y='191.334'/>
+<use x='180.138' xlink:href='#g3-98' y='191.334'/>
+<use x='184.746' xlink:href='#g3-101' y='191.334'/>
+<use x='188.509' xlink:href='#g3-110' y='191.334'/>
+<use x='192.882' xlink:href='#g3-99' y='191.334'/>
+<use x='196.646' xlink:href='#g3-104' y='191.334'/>
+<use x='201.018' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' xlink:href='#g3-115' y='191.334'/>
+<use x='171.531' xlink:href='#g3-104' y='191.334'/>
+<use x='175.904' xlink:href='#g3-56' y='191.334'/>
+<use x='180.138' xlink:href='#g3-98' y='191.334'/>
+<use x='184.746' xlink:href='#g3-101' y='191.334'/>
+<use x='188.509' xlink:href='#g3-110' y='191.334'/>
+<use x='192.882' xlink:href='#g3-99' y='191.334'/>
+<use x='196.646' xlink:href='#g3-104' y='191.334'/>
+<use x='201.018' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' xlink:href='#g3-120' y='191.334'/>
+<use x='172.187' xlink:href='#g3-109' y='191.334'/>
+<use x='178.912' xlink:href='#g3-97' y='191.334'/>
+<use x='182.98' xlink:href='#g3-108' y='191.334'/>
+<use x='185' xlink:href='#g3-108' y='191.334'/>
+<use x='187.02' xlink:href='#g3-111' y='191.334'/>
+<use x='191.49' xlink:href='#g3-99' y='191.334'/>
+<use x='195.254' xlink:href='#g3-45' y='191.334'/>
+<use x='198.076' xlink:href='#g3-116' y='191.334'/>
+<use x='201.134' xlink:href='#g3-101' y='191.334'/>
+<use x='204.898' xlink:href='#g3-115' y='191.334'/>
+<use x='208.144' xlink:href='#g3-116' y='191.334'/>
+<use x='211.202' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' xlink:href='#g3-99' y='191.334'/>
+<use x='172.049' xlink:href='#g3-97' y='191.334'/>
+<use x='176.117' xlink:href='#g3-99' y='191.334'/>
+<use x='179.88' xlink:href='#g3-104' y='191.334'/>
+<use x='184.253' xlink:href='#g3-101' y='191.334'/>
+<use x='188.017' xlink:href='#g3-45' y='191.334'/>
+<use x='190.839' xlink:href='#g3-115' y='191.334'/>
+<use x='194.086' xlink:href='#g3-99' y='191.334'/>
+<use x='197.849' xlink:href='#g3-114' y='191.334'/>
+<use x='200.741' xlink:href='#g3-97' y='191.334'/>
+<use x='204.81' xlink:href='#g3-116' y='191.334'/>
+<use x='207.868' xlink:href='#g3-99' y='191.334'/>
+<use x='211.631' xlink:href='#g3-104' y='191.334'/>
+<use x='216.004' xlink:href='#g3-78' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' xlink:href='#g2-48' y='191.334'/>
+<use x='170.931' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' xlink:href='#g2-48' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-120' y='191.334'/>
+</g>
+<path clip-path='url(#clip6)' d='M135.949 184.824H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M142.742 251.93H145.981V184.824H142.742ZM201.41 251.93H204.649V184.824H201.41ZM260.078 251.93H263.317V184.824H260.078ZM318.75 251.93H321.988V184.824H318.75ZM377.418 251.93H380.656V184.824H377.418ZM436.086 251.93H439.324V184.824H436.086Z' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M142.742 251.93H145.981V184.824H142.742ZM201.41 251.93H204.649V184.824H201.41ZM260.078 251.93H263.317V184.824H260.078ZM318.75 251.93H321.988V184.824H318.75ZM377.418 251.93H380.656V184.824H377.418ZM436.086 251.93H439.324V184.824H436.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M144.359 184.824V184.488' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M144.359 184.824V184.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M142.367 184.489H146.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M144.359 184.824V185.16' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M144.359 184.824V185.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M146.352 185.161H142.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M203.031 184.824V184.488' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M203.031 184.824V184.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M201.039 184.489H205.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M203.031 184.824V185.16' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M203.031 184.824V185.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M205.023 185.161H201.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M261.699 184.824V182.742' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M261.699 184.824V182.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M259.707 182.742H263.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M261.699 184.824V186.902' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M261.699 184.824V186.902' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M263.691 186.902H259.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M320.367 184.824V183.012' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M320.367 184.824V183.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M318.375 183.012H322.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M320.367 184.824V186.637' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M320.367 184.824V186.637' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M322.359 186.637H318.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M379.035 184.824V184.352' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M379.035 184.824V184.352' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M377.043 184.351H381.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M379.035 184.824V185.293' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M379.035 184.824V185.293' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M381.027 185.293H377.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M437.707 184.824V183.949' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M437.707 184.824V183.949' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M435.715 183.95H439.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M437.707 184.824V185.695' fill='#993333'/>
+<path clip-path='url(#clip6)' d='M437.707 184.824V185.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M439.699 185.695H435.711' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M147.973 251.93H151.211V184.285H147.973ZM206.641 251.93H209.879V179.926H206.641ZM265.309 251.93H268.547V98.523H265.309ZM323.981 251.93H327.219V84.164H323.981ZM382.649 251.93H385.887V84.164H382.649ZM441.317 251.93H444.555V84.164H441.317Z' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M147.973 251.93H151.211V184.285H147.973ZM206.641 251.93H209.879V179.926H206.641ZM265.309 251.93H268.547V98.523H265.309ZM323.981 251.93H327.219V84.164H323.981ZM382.649 251.93H385.887V84.164H382.649ZM441.317 251.93H444.555V84.164H441.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M149.59 184.285V183.949' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M149.59 184.285V183.949' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M147.598 183.95H151.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M149.59 184.285V184.621' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M149.59 184.285V184.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M151.582 184.621H147.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M208.262 179.926V179.523' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M208.262 179.926V179.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M206.27 179.524H210.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M208.262 179.926V180.328' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M208.262 179.926V180.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M210.253 180.328H206.265' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M266.93 98.523V94.902' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M266.93 98.523V94.902' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M264.938 94.902H268.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M266.93 98.523V102.148' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M266.93 98.523V102.148' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M268.921 102.148H264.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M325.598 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M323.606 84.164H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M325.598 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M323.606 84.164H327.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M384.266 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M382.274 84.164H386.262' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M384.266 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M382.274 84.164H386.262' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M442.938 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M440.946 84.164H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M442.938 84.164V84.164' fill='#8080bf'/>
+<path clip-path='url(#clip6)' d='M440.946 84.164H444.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M153.203 251.93H156.442V178.715H153.203ZM211.871 251.93H215.11V178.047H211.871ZM270.539 251.93H273.777V85.773H270.539ZM329.211 251.93H332.449V88.996H329.211ZM387.879 251.93H391.117V84.164H387.879ZM446.547 251.93H449.785V84.164H446.547Z' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M153.203 251.93H156.442V178.715H153.203ZM211.871 251.93H215.11V178.047H211.871ZM270.539 251.93H273.777V85.773H270.539ZM329.211 251.93H332.449V88.996H329.211ZM387.879 251.93H391.117V84.164H387.879ZM446.547 251.93H449.785V84.164H446.547Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M154.82 178.715V178.047' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M154.82 178.715V178.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M152.828 178.047H156.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M154.82 178.715V179.387' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M154.82 178.715V179.387' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M156.813 179.386H152.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M213.492 178.047V177.574' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M213.492 178.047V177.574' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M211.5 177.575H215.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M213.492 178.047V178.516' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M213.492 178.047V178.516' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M215.484 178.516H211.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M272.16 85.773V83.558' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M272.16 85.773V83.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M270.168 83.559H274.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M272.16 85.773V87.988' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M272.16 85.773V87.988' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M274.152 87.988H270.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M330.828 88.996V86.715' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M330.828 88.996V86.715' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M328.836 86.715H332.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M330.828 88.996V91.277' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M330.828 88.996V91.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M332.82 91.277H328.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M389.496 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M387.504 84.164H391.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M389.496 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M387.504 84.164H391.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M448.168 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M446.176 84.164H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M448.168 84.164V84.164' fill='#ffb733'/>
+<path clip-path='url(#clip6)' d='M446.176 84.164H450.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M158.434 251.93H161.672V155.164H158.434ZM217.102 251.93H220.34V156.305H217.102ZM275.77 251.93H279.008V84.164H275.77ZM334.442 251.93H337.68V84.164H334.442ZM393.109 251.93H396.348V131.609H393.109ZM451.777 251.93H455.016V183.949H451.777Z' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M158.434 251.93H161.672V155.164H158.434ZM217.102 251.93H220.34V156.305H217.102ZM275.77 251.93H279.008V84.164H275.77ZM334.442 251.93H337.68V84.164H334.442ZM393.109 251.93H396.348V131.609H393.109ZM451.777 251.93H455.016V183.949H451.777Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M160.051 155.164V154.758' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M160.051 155.164V154.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M158.058 154.758H162.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M160.051 155.164V155.566' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M160.051 155.164V155.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M162.043 155.567H158.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M218.723 156.305V156.102' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M218.723 156.305V156.102' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M216.73 156.102H220.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M218.723 156.305V156.504' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M218.723 156.305V156.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M220.714 156.504H216.726' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M277.391 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M275.398 84.164H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M277.391 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M275.398 84.164H279.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M336.059 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M334.066 84.164H338.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M336.059 84.164V84.164' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M334.066 84.164H338.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M394.727 131.609V131.406' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M394.727 131.609V131.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M392.734 131.407H396.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M394.727 131.609V131.808' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M394.727 131.609V131.808' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M396.718 131.808H392.734' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M453.399 183.949V182.809' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M453.399 183.949V182.809' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M451.406 182.809H455.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M453.399 183.949V185.09' fill='#bf80bf'/>
+<path clip-path='url(#clip6)' d='M453.399 183.949V185.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M455.39 185.089H451.402' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M163.664 251.93H166.903V180.664H163.664ZM222.332 251.93H225.57V183.078H222.332ZM281 251.93H284.238V174.355H281ZM339.672 251.93H342.91V183.144H339.672ZM398.34 251.93H401.578V198.914H398.34ZM457.008 251.93H460.246V184.555H457.008Z' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M163.664 251.93H166.903V180.664H163.664ZM222.332 251.93H225.57V183.078H222.332ZM281 251.93H284.238V174.355H281ZM339.672 251.93H342.91V183.144H339.672ZM398.34 251.93H401.578V198.914H398.34ZM457.008 251.93H460.246V184.555H457.008Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M165.281 180.664V180.461' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M165.281 180.664V180.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M163.289 180.461H167.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M165.281 180.664V180.863' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M165.281 180.664V180.863' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M167.274 180.864H163.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M223.953 183.078V182.809' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M223.953 183.078V182.809' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M221.961 182.809H225.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M223.953 183.078V183.348' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M223.953 183.078V183.348' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M225.945 183.348H221.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M282.621 174.355V174.355' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M280.629 174.355H284.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M282.621 174.355V174.355' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M280.629 174.355H284.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M341.289 183.144V182.473' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M341.289 183.144V182.473' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M339.297 182.472H343.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M341.289 183.144V183.816' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M341.289 183.144V183.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M343.281 183.816H339.297' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M399.957 198.914V197.977' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M399.957 198.914V197.977' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M397.965 197.977H401.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M399.957 198.914V199.855' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M399.957 198.914V199.855' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M401.949 199.856H397.965' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M458.629 184.555V184.555' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M456.637 184.555H460.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M458.629 184.555V184.555' fill='#dfbf9f'/>
+<path clip-path='url(#clip6)' d='M456.637 184.555H460.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M168.895 251.93H172.133V173.684H168.895ZM227.563 251.93H230.801V84.164H227.563ZM286.231 251.93H289.469V84.164H286.231ZM344.902 251.93H348.141V84.164H344.902ZM403.57 251.93H406.809V84.164H403.57ZM462.238 251.93H465.477V84.164H462.238Z' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M168.895 251.93H172.133V173.684H168.895ZM227.563 251.93H230.801V84.164H227.563ZM286.231 251.93H289.469V84.164H286.231ZM344.902 251.93H348.141V84.164H344.902ZM403.57 251.93H406.809V84.164H403.57ZM462.238 251.93H465.477V84.164H462.238Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M170.512 173.684V173.348' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M170.512 173.684V173.348' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M168.519 173.348H172.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M170.512 173.684V174.019' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M170.512 173.684V174.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M172.504 174.02H168.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M229.184 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M227.191 84.164H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M229.184 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M227.191 84.164H231.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M287.852 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M285.859 84.164H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M287.852 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M285.859 84.164H289.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M346.52 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M344.527 84.164H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M346.52 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M344.527 84.164H348.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M405.188 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M403.195 84.164H407.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M405.188 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M403.195 84.164H407.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M463.859 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M461.867 84.164H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M463.859 84.164V84.164' fill='#80bf80'/>
+<path clip-path='url(#clip6)' d='M461.867 84.164H465.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M174.125 251.93H177.363V147.109H174.125ZM232.793 251.93H236.031V139.93H232.793ZM291.461 251.93H294.699V84.164H291.461ZM350.133 251.93H353.371V245.219H350.133ZM408.801 251.93H412.039V245.219H408.801ZM467.469 251.93H470.707V183.144H467.469Z' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M174.125 251.93H177.363V147.109H174.125ZM232.793 251.93H236.031V139.93H232.793ZM291.461 251.93H294.699V84.164H291.461ZM350.133 251.93H353.371V245.219H350.133ZM408.801 251.93H412.039V245.219H408.801ZM467.469 251.93H470.707V183.144H467.469Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M175.742 147.109V144.289' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M175.742 147.109V144.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M173.75 144.289H177.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M175.742 147.109V149.93' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M175.742 147.109V149.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M177.735 149.93H173.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M234.414 139.93V130.937' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M234.414 139.93V130.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M232.422 130.938H236.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M234.414 139.93V148.922' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M234.414 139.93V148.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M236.403 148.922H232.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M293.082 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M291.09 84.164H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M293.082 84.164V84.164' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M291.09 84.164H295.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M351.75 245.219V245.219' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M349.758 245.219H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M351.75 245.219V245.219' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M349.758 245.219H353.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M410.418 245.219V245.219' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M408.426 245.219H412.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M410.418 245.219V245.219' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M408.426 245.219H412.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M469.09 183.144V181.734' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M469.09 183.144V181.734' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M467.098 181.734H471.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M469.09 183.144V184.555' fill='#bfbf80'/>
+<path clip-path='url(#clip6)' d='M469.09 183.144V184.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M471.082 184.555H467.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M179.356 251.93H182.594V169.254H179.356ZM238.024 251.93H241.262V169.387H238.024ZM296.692 251.93H299.93V84.164H296.692ZM355.363 251.93H358.602V84.164H355.363ZM414.031 251.93H417.27V84.164H414.031ZM472.699 251.93H475.938V84.164H472.699Z' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M179.356 251.93H182.594V169.254H179.356ZM238.024 251.93H241.262V169.387H238.024ZM296.692 251.93H299.93V84.164H296.692ZM355.363 251.93H358.602V84.164H355.363ZM414.031 251.93H417.27V84.164H414.031ZM472.699 251.93H475.938V84.164H472.699Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M180.973 169.254V168.719' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M180.973 169.254V168.719' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M178.98 168.719H182.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M180.973 169.254V169.793' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M180.973 169.254V169.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M182.965 169.793H178.98' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M239.645 169.387V169.187' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M239.645 169.387V169.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M237.652 169.187H241.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M239.645 169.387V169.59' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M239.645 169.387V169.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M241.633 169.59H237.648' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M298.313 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M296.32 84.164H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M298.313 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M296.32 84.164H300.304' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M356.981 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M354.988 84.164H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M356.981 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M354.988 84.164H358.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M415.649 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M413.656 84.164H417.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M415.649 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M413.656 84.164H417.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M474.32 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M472.328 84.164H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M474.32 84.164V84.164' fill='#339999'/>
+<path clip-path='url(#clip6)' d='M472.328 84.164H476.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M184.586 251.93H187.824V180.328H184.586ZM243.254 251.93H246.492V179.59H243.254ZM301.922 251.93H305.16V84.164H301.922ZM360.594 251.93H363.832V107.516H360.594ZM419.262 251.93H422.5V175.43H419.262ZM477.93 251.93H481.168V182.406H477.93Z' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M184.586 251.93H187.824V180.328H184.586ZM243.254 251.93H246.492V179.59H243.254ZM301.922 251.93H305.16V84.164H301.922ZM360.594 251.93H363.832V107.516H360.594ZM419.262 251.93H422.5V175.43H419.262ZM477.93 251.93H481.168V182.406H477.93Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M186.203 180.328V179.992' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M186.203 180.328V179.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M184.211 179.992H188.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M186.203 180.328V180.664' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M186.203 180.328V180.664' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M188.196 180.664H184.211' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M244.875 179.59V179.187' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M244.875 179.59V179.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M242.883 179.187H246.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M244.875 179.59V179.992' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M244.875 179.59V179.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M246.864 179.992H242.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M303.543 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M301.551 84.164H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M303.543 84.164V84.164' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M301.551 84.164H305.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M362.211 107.516V104.094' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M362.211 107.516V104.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M360.219 104.093H364.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M362.211 107.516V110.937' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M362.211 107.516V110.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M364.203 110.937H360.219' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M420.879 175.43V175.16' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M420.879 175.43V175.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M418.887 175.16H422.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M420.879 175.43V175.695' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M420.879 175.43V175.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M422.871 175.696H418.887' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M479.551 182.406V181.199' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M479.551 182.406V181.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M477.559 181.199H481.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M479.551 182.406V183.613' fill='#bf8080'/>
+<path clip-path='url(#clip6)' d='M479.551 182.406V183.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M481.543 183.613H477.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M420.539 312.98H487.762V278.973H420.539Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 255.575 118.327)'>
+<use x='168.285' xlink:href='#g2-114' y='167.424'/>
+<use x='170.092' xlink:href='#g2-53' y='167.424'/>
+<use x='172.739' xlink:href='#g2-97' y='167.424'/>
+<use x='175.281' xlink:href='#g2-45' y='167.424'/>
+<use x='177.046' xlink:href='#g2-49' y='167.424'/>
+<use x='179.692' xlink:href='#g2-50' y='167.424'/>
+<use x='182.338' xlink:href='#g2-120' y='167.424'/>
+<use x='184.777' xlink:href='#g2-108' y='167.424'/>
+<use x='186.04' xlink:href='#g2-97' y='167.424'/>
+<use x='188.435' xlink:href='#g2-114' y='167.424'/>
+<use x='190.243' xlink:href='#g2-103' y='167.424'/>
+<use x='192.889' xlink:href='#g2-101' y='167.424'/>
+<use x='195.241' xlink:href='#g2-44' y='167.424'/>
+<use x='198.476' xlink:href='#g2-51' y='167.424'/>
+<use x='201.122' xlink:href='#g2-56' y='167.424'/>
+<use x='203.769' xlink:href='#g2-52' y='167.424'/>
+<use x='206.415' xlink:href='#g2-71' y='167.424'/>
+<use x='209.943' xlink:href='#g2-98' y='167.424'/>
+<use x='168.285' xlink:href='#g2-52' y='173.401'/>
+<use x='170.931' xlink:href='#g2-56' y='173.401'/>
+<use x='175.342' xlink:href='#g2-112' y='173.401'/>
+<use x='177.928' xlink:href='#g2-114' y='173.401'/>
+<use x='179.735' xlink:href='#g2-111' y='173.401'/>
+<use x='182.529' xlink:href='#g2-99' y='173.401'/>
+<use x='186.645' xlink:href='#g2-65' y='173.401'/>
+<use x='190.174' xlink:href='#g2-77' y='173.401'/>
+<use x='194.792' xlink:href='#g2-68' y='173.401'/>
+<use x='200.378' xlink:href='#g2-64' y='173.401'/>
+<use x='203.907' xlink:href='#g2-50' y='173.401'/>
+<use x='206.553' xlink:href='#g2-46' y='173.401'/>
+<use x='208.024' xlink:href='#g2-53' y='173.401'/>
+<use x='210.67' xlink:href='#g2-71' y='173.401'/>
+<use x='214.198' xlink:href='#g2-104' y='173.401'/>
+<use x='216.931' xlink:href='#g2-122' y='173.401'/>
+<use x='168.285' xlink:href='#g2-85' y='179.379'/>
+<use x='171.917' xlink:href='#g2-98' y='179.379'/>
+<use x='174.65' xlink:href='#g2-117' y='179.379'/>
+<use x='177.383' xlink:href='#g2-110' y='179.379'/>
+<use x='180.116' xlink:href='#g2-116' y='179.379'/>
+<use x='182.027' xlink:href='#g2-117' y='179.379'/>
+<use x='186.524' xlink:href='#g2-49' y='179.379'/>
+<use x='189.17' xlink:href='#g2-56' y='179.379'/>
+<use x='191.817' xlink:href='#g2-46' y='179.379'/>
+<use x='193.287' xlink:href='#g2-48' y='179.379'/>
+<use x='195.933' xlink:href='#g2-52' y='179.379'/>
+<use x='198.58' xlink:href='#g2-46' y='179.379'/>
+<use x='200.05' xlink:href='#g2-49' y='179.379'/>
+<use x='202.696' xlink:href='#g2-44' y='179.379'/>
+<use x='205.931' xlink:href='#g2-71' y='179.379'/>
+<use x='209.459' xlink:href='#g2-67' y='179.379'/>
+<use x='212.841' xlink:href='#g2-67' y='179.379'/>
+<use x='217.986' xlink:href='#g2-55' y='179.379'/>
+<use x='220.633' xlink:href='#g2-46' y='179.379'/>
+<use x='222.103' xlink:href='#g2-52' y='179.379'/>
+<use x='224.749' xlink:href='#g2-46' y='179.379'/>
+<use x='226.219' xlink:href='#g2-48' y='179.379'/>
+<use x='168.285' xlink:href='#g2-50' y='185.357'/>
+<use x='170.931' xlink:href='#g2-52' y='185.357'/>
+<use x='175.342' xlink:href='#g2-99' y='185.357'/>
+<use x='177.694' xlink:href='#g2-111' y='185.357'/>
+<use x='180.193' xlink:href='#g2-114' y='185.357'/>
+<use x='182.001' xlink:href='#g2-101' y='185.357'/>
+<use x='184.353' xlink:href='#g2-115' y='185.357'/>
+<use x='188.146' xlink:href='#g2-111' y='185.357'/>
+<use x='190.793' xlink:href='#g2-110' y='185.357'/>
+<use x='195.29' xlink:href='#g2-51' y='185.357'/>
+<use x='199.7' xlink:href='#g2-110' y='185.357'/>
+<use x='202.433' xlink:href='#g2-117' y='185.357'/>
+<use x='205.166' xlink:href='#g2-109' y='185.357'/>
+<use x='209.369' xlink:href='#g2-97' y='185.357'/>
+<use x='213.676' xlink:href='#g2-110' y='185.357'/>
+<use x='216.409' xlink:href='#g2-111' y='185.357'/>
+<use x='219.202' xlink:href='#g2-100' y='185.357'/>
+<use x='221.935' xlink:href='#g2-101' y='185.357'/>
+<use x='224.287' xlink:href='#g2-115' y='185.357'/>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-48' y='191.334'/>
+<use x='173.578' xlink:href='#g2-50' y='191.334'/>
+<use x='176.224' xlink:href='#g2-48' y='191.334'/>
+<use x='178.87' xlink:href='#g2-45' y='191.334'/>
+<use x='180.635' xlink:href='#g2-48' y='191.334'/>
+<use x='183.281' xlink:href='#g2-49' y='191.334'/>
+<use x='185.927' xlink:href='#g2-45' y='191.334'/>
+<use x='187.692' xlink:href='#g2-49' y='191.334'/>
+<use x='190.338' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -45.339 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 13.33 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 71.999 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.668 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 189.337 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 248.006 346.904)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.108 346.367)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.561 342.005)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 77.23 260.606)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.899 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-53' y='191.334'/>
+<use x='176.558' xlink:href='#g2-54' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-54' y='191.334'/>
+<use x='183.321' xlink:href='#g2-52' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.568 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-55' y='191.334'/>
+<use x='179.205' xlink:href='#g2-50' y='191.334'/>
+<use x='181.851' xlink:href='#g2-46' y='191.334'/>
+<use x='183.321' xlink:href='#g2-48' y='191.334'/>
+<use x='185.968' xlink:href='#g2-51' y='191.334'/>
+<use x='188.614' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 253.236 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-55' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-50' y='191.334'/>
+<use x='183.321' xlink:href='#g2-57' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -34.878 340.797)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.791 340.126)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.46 247.855)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-52' y='191.334'/>
+<use x='175.048' xlink:href='#g2-56' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 141.129 251.077)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-52' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.798 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-52' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-55' y='191.334'/>
+<use x='180.675' xlink:href='#g2-55' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 258.467 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-55' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-49' y='191.334'/>
+<use x='183.321' xlink:href='#g2-48' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.648 317.243)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-52' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 29.021 318.384)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-52' y='191.334'/>
+<use x='175.048' xlink:href='#g2-50' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.69 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-52' y='191.334'/>
+<use x='180.675' xlink:href='#g2-56' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.359 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-57' y='191.334'/>
+<use x='180.675' xlink:href='#g2-51' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 205.028 293.689)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-55' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 263.697 346.032)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-49' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.417 342.743)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 34.252 345.159)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.921 336.435)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.59 345.226)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-50' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 210.259 360.996)'>
+<use x='168.285' xlink:href='#g2-48' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-55' y='191.334'/>
+<use x='175.048' xlink:href='#g2-57' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 268.928 346.636)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-48' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.187 335.764)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.482 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-53' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-51' y='191.334'/>
+<use x='180.675' xlink:href='#g2-53' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 98.151 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-51' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-57' y='191.334'/>
+<use x='183.321' xlink:href='#g2-50' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.82 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-53' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-54' y='191.334'/>
+<use x='180.675' xlink:href='#g2-48' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.489 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-55' y='191.334'/>
+<use x='176.558' xlink:href='#g2-49' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-54' y='191.334'/>
+<use x='183.321' xlink:href='#g2-57' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 274.158 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-53' y='191.334'/>
+<use x='180.675' xlink:href='#g2-54' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -13.956 309.19)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-53' y='191.334'/>
+<use x='175.048' xlink:href='#g2-54' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.713 302.01)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-54' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.382 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-51' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-51' y='191.334'/>
+<use x='183.321' xlink:href='#g2-55' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.523 407.299)'>
+<use x='168.285' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.192 407.299)'>
+<use x='168.285' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 279.389 345.226)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -8.726 331.335)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.943 331.47)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-50' y='191.334'/>
+<use x='175.048' xlink:href='#g2-51' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.612 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-49' y='191.334'/>
+<use x='176.558' xlink:href='#g2-55' y='191.334'/>
+<use x='179.205' xlink:href='#g2-46' y='191.334'/>
+<use x='180.675' xlink:href='#g2-55' y='191.334'/>
+<use x='183.321' xlink:href='#g2-52' y='191.334'/>
+<use x='185.968' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 167.281 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-52' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-57' y='191.334'/>
+<use x='180.675' xlink:href='#g2-57' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.95 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-53' y='191.334'/>
+<use x='180.675' xlink:href='#g2-53' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 284.619 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-53' y='191.334'/>
+<use x='180.675' xlink:href='#g2-57' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.495 342.408)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-55' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 55.174 341.67)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-56' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.843 246.245)'>
+<use x='163.396' xlink:href='#g4-1' y='191.334'/>
+<use x='166.901' xlink:href='#g4-1' y='191.334'/>
+<use x='170.407' xlink:href='#g4-1' y='191.334'/>
+<use x='173.912' xlink:href='#g2-51' y='191.334'/>
+<use x='176.558' xlink:href='#g2-46' y='191.334'/>
+<use x='178.029' xlink:href='#g2-50' y='191.334'/>
+<use x='180.675' xlink:href='#g2-48' y='191.334'/>
+<use x='183.321' xlink:href='#g2-120' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.512 269.598)'>
+<use x='168.285' xlink:href='#g2-50' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-53' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 231.181 337.509)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-49' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 289.85 344.488)'>
+<use x='168.285' xlink:href='#g2-49' y='191.334'/>
+<use x='170.931' xlink:href='#g2-46' y='191.334'/>
+<use x='172.401' xlink:href='#g2-48' y='191.334'/>
+<use x='175.048' xlink:href='#g2-52' y='191.334'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.176 391.591)'>
+<use x='168.285' xlink:href='#g1-82' y='191.334'/>
+<use x='174.255' xlink:href='#g1-101' y='191.334'/>
+<use x='178.351' xlink:href='#g1-108' y='191.334'/>
+<use x='180.551' xlink:href='#g1-97' y='191.334'/>
+<use x='184.979' xlink:href='#g1-116' y='191.334'/>
+<use x='188.307' xlink:href='#g1-105' y='191.334'/>
+<use x='190.507' xlink:href='#g1-118' y='191.334'/>
+<use x='194.755' xlink:href='#g1-101' y='191.334'/>
+<use x='201.922' xlink:href='#g1-116' y='191.334'/>
+<use x='205.25' xlink:href='#g1-105' y='191.334'/>
+<use x='207.45' xlink:href='#g1-109' y='191.334'/>
+<use x='214.77' xlink:href='#g1-101' y='191.334'/>
+<use x='221.937' xlink:href='#g3-40' y='191.334'/>
+<use x='225.231' xlink:href='#g3-108' y='191.334'/>
+<use x='227.251' xlink:href='#g3-111' y='191.334'/>
+<use x='231.25' xlink:href='#g3-119' y='191.334'/>
+<use x='236.799' xlink:href='#g3-101' y='191.334'/>
+<use x='240.562' xlink:href='#g3-114' y='191.334'/>
+<use x='246.277' xlink:href='#g3-105' y='191.334'/>
+<use x='248.297' xlink:href='#g3-115' y='191.334'/>
+<use x='254.366' xlink:href='#g3-98' y='191.334'/>
+<use x='258.974' xlink:href='#g3-101' y='191.334'/>
+<use x='262.738' xlink:href='#g3-116' y='191.334'/>
+<use x='265.796' xlink:href='#g3-116' y='191.334'/>
+<use x='268.854' xlink:href='#g3-101' y='191.334'/>
+<use x='272.618' xlink:href='#g3-114' y='191.334'/>
+<use x='275.51' xlink:href='#g3-41' y='191.334'/>
+</g>
+<path d='M136.149 312.324H341.363V282.324H136.149Z' fill='#ffffff'/>
+<path d='M136.149 312.324H341.363V282.324H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' fill='#993333'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='195.372' xlink:href='#g3-120' y='178.327'/>
+<use x='199.274' xlink:href='#g3-109' y='178.327'/>
+<use x='205.999' xlink:href='#g3-105' y='178.327'/>
+<use x='208.019' xlink:href='#g3-58' y='178.327'/>
+<use x='210.371' xlink:href='#g0-57' y='178.327'/>
+<use x='214.076' xlink:href='#g0-57' y='178.327'/>
+</g>
+<path d='M184.145 292.816H187.133V284.844H184.145ZM190.121 292.816H193.109V286.836H190.121Z' fill='#8080bf'/>
+<path d='M184.145 292.816H187.133V284.844H184.145ZM190.121 292.816H193.109V286.836H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='239.382' xlink:href='#g3-116' y='178.327'/>
+<use x='242.44' xlink:href='#g3-99' y='178.327'/>
+<use x='246.204' xlink:href='#g3-58' y='178.327'/>
+<use x='248.556' xlink:href='#g0-53' y='178.327'/>
+<use x='252.261' xlink:href='#g0-54' y='178.327'/>
+</g>
+<path d='M227.356 292.816H230.344V284.844H227.356ZM233.332 292.816H236.32V286.836H233.332Z' fill='#ffb733'/>
+<path d='M227.356 292.816H230.344V284.844H227.356ZM233.332 292.816H236.32V286.836H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='281.863' xlink:href='#g3-106' y='178.327'/>
+<use x='284.119' xlink:href='#g3-101' y='178.327'/>
+<use x='287.882' xlink:href='#g3-58' y='178.327'/>
+<use x='290.235' xlink:href='#g0-53' y='178.327'/>
+<use x='293.94' xlink:href='#g0-50' y='178.327'/>
+</g>
+<path d='M269.106 292.816H272.094V284.844H269.106ZM275.086 292.816H278.074V286.836H275.086Z' fill='#bf80bf'/>
+<path d='M269.106 292.816H272.094V284.844H269.106ZM275.086 292.816H278.074V286.836H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='321.287' xlink:href='#g3-116' y='178.327'/>
+<use x='324.345' xlink:href='#g3-98' y='178.327'/>
+<use x='328.717' xlink:href='#g3-98' y='178.327'/>
+<use x='333.09' xlink:href='#g3-58' y='178.327'/>
+<use x='335.442' xlink:href='#g0-53' y='178.327'/>
+<use x='339.147' xlink:href='#g0-51' y='178.327'/>
+</g>
+<path d='M306.203 292.816H309.191V284.844H306.203ZM312.18 292.816H315.168V286.836H312.18Z' fill='#dfbf9f'/>
+<path d='M306.203 292.816H309.191V284.844H306.203ZM312.18 292.816H315.168V286.836H312.18Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='356.019' xlink:href='#g3-114' y='178.327'/>
+<use x='358.911' xlink:href='#g3-112' y='178.327'/>
+<use x='363.284' xlink:href='#g3-58' y='178.327'/>
+<use x='365.636' xlink:href='#g0-56' y='178.327'/>
+<use x='369.341' xlink:href='#g0-54' y='178.327'/>
+</g>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' fill='#80bf80'/>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='195.372' xlink:href='#g3-104' y='191.334'/>
+<use x='199.744' xlink:href='#g3-111' y='191.334'/>
+<use x='203.978' xlink:href='#g3-97' y='191.334'/>
+<use x='207.811' xlink:href='#g3-114' y='191.334'/>
+<use x='210.703' xlink:href='#g3-100' y='191.334'/>
+<use x='215.076' xlink:href='#g3-58' y='191.334'/>
+<use x='217.428' xlink:href='#g0-51' y='191.334'/>
+<use x='221.133' xlink:href='#g0-51' y='191.334'/>
+</g>
+<path d='M184.145 305.82H187.133V297.852H184.145ZM190.121 305.82H193.109V299.844H190.121Z' fill='#bfbf80'/>
+<path d='M184.145 305.82H187.133V297.852H184.145ZM190.121 305.82H193.109V299.844H190.121Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='239.382' xlink:href='#g3-109' y='191.334'/>
+<use x='246.107' xlink:href='#g3-101' y='191.334'/>
+<use x='249.871' xlink:href='#g3-115' y='191.334'/>
+<use x='253.117' xlink:href='#g3-104' y='191.334'/>
+<use x='257.489' xlink:href='#g3-58' y='191.334'/>
+<use x='259.842' xlink:href='#g0-51' y='191.334'/>
+<use x='263.547' xlink:href='#g0-52' y='191.334'/>
+</g>
+<path d='M227.356 305.82H230.344V297.852H227.356ZM233.332 305.82H236.32V299.844H233.332Z' fill='#339999'/>
+<path d='M227.356 305.82H230.344V297.852H227.356ZM233.332 305.82H236.32V299.844H233.332Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='281.863' xlink:href='#g3-103' y='191.334'/>
+<use x='286.097' xlink:href='#g3-108' y='191.334'/>
+<use x='288.118' xlink:href='#g3-105' y='191.334'/>
+<use x='290.138' xlink:href='#g3-98' y='191.334'/>
+<use x='294.746' xlink:href='#g3-99' y='191.334'/>
+<use x='298.509' xlink:href='#g3-58' y='191.334'/>
+<use x='300.862' xlink:href='#g0-52' y='191.334'/>
+<use x='304.567' xlink:href='#g0-51' y='191.334'/>
+</g>
+<path d='M269.106 305.82H272.094V297.852H269.106ZM275.086 305.82H278.074V299.844H275.086Z' fill='#bf8080'/>
+<path d='M269.106 305.82H272.094V297.852H269.106ZM275.086 305.82H278.074V299.844H275.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='321.287' xlink:href='#g3-115' y='191.334'/>
+<use x='324.533' xlink:href='#g3-109' y='191.334'/>
+<use x='331.258' xlink:href='#g3-105' y='191.334'/>
+<use x='333.278' xlink:href='#g3-58' y='191.334'/>
+<use x='335.63' xlink:href='#g0-54' y='191.334'/>
+<use x='339.335' xlink:href='#g0-57' y='191.334'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-2.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-2.svg
new file mode 100644 (file)
index 0000000..917ea57
--- /dev/null
@@ -0,0 +1,983 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='243.704pt' version='1.1' viewBox='106.737 54.995 381.623 243.704' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip2'>
+<path d='M135.949 249.281H487.961V81.515H135.949Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-45' transform='scale(1.6)' xlink:href='#g1-45'/>
+<use id='g2-49' transform='scale(1.6)' xlink:href='#g1-49'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M2.002 -3.457H1.519L0.149 0H0.558L0.946 -0.986H2.461L2.849 0H3.372L2.002 -3.457ZM1.709 -3.078L2.336 -1.28H1.071L1.709 -3.078Z' id='g1-65'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M0.488 -3.457V0H1.903C2.8 0 3.522 -0.757 3.522 -1.699C3.522 -2.675 2.795 -3.457 1.903 -3.457H0.488ZM0.976 -0.294V-3.163H1.768C2.451 -3.163 3.034 -2.62 3.034 -1.704C3.034 -0.777 2.426 -0.294 1.768 -0.294H0.976Z' id='g1-68'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M2.775 -1.729C2.715 -1.579 2.356 -0.702 2.306 -0.493H2.301C2.267 -0.638 2.037 -1.21 1.988 -1.34L1.131 -3.457H0.523V0H0.941V-3.059H0.946C0.986 -2.884 1.245 -2.227 1.27 -2.172L2.102 -0.105H2.496L3.238 -1.938C3.238 -1.943 3.582 -2.79 3.666 -3.064H3.671V0H4.09V-3.457H3.477L2.775 -1.729Z' id='g1-77'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.361 -2.212H1.958C1.554 -1.26 1.275 -0.618 1.255 -0.314C1.245 -0.453 1.156 -0.702 1.066 -0.936C0.986 -1.136 0.907 -1.335 0.817 -1.529L0.503 -2.212H0.075L1.106 0C1.046 0.144 0.946 0.374 0.917 0.438C0.812 0.648 0.742 0.717 0.608 0.717C0.588 0.717 0.403 0.717 0.189 0.628L0.219 0.976C0.264 0.986 0.448 1.016 0.603 1.016C0.802 1.016 0.981 0.941 1.191 0.463L2.361 -2.212Z' id='g1-121'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g0-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page2'>
+<path d='M194.617 258.136V249.281M253.285 258.136V249.281M311.953 258.136V249.281M370.625 258.136V249.281M429.293 258.136V249.281M194.617 72.66V81.515M253.285 72.66V81.515M311.953 72.66V81.515M370.625 72.66V81.515M429.293 72.66V81.515' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 253.535V249.281M223.953 253.535V249.281M282.621 253.535V249.281M341.289 253.535V249.281M399.957 253.535V249.281M458.629 253.535V249.281M165.281 77.265V81.515M223.953 77.265V81.515M282.621 77.265V81.515M341.289 77.265V81.515M399.957 77.265V81.515M458.629 77.265V81.515' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281H140.199M135.949 215.73H140.199M135.949 182.176H140.199M135.949 148.625H140.199M135.949 115.07H140.199M135.949 81.515H140.199M487.961 249.281H483.711M487.961 215.73H483.711M487.961 182.176H483.711M487.961 148.625H483.711M487.961 115.07H483.711M487.961 81.515H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281V81.515H487.961V249.281H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 61.588)'>
+<use x='168.285' xlink:href='#g2-97' y='201.694'/>
+<use x='172.353' xlink:href='#g2-108' y='201.694'/>
+<use x='174.373' xlink:href='#g2-108' y='201.694'/>
+<use x='176.393' xlink:href='#g2-111' y='201.694'/>
+<use x='180.863' xlink:href='#g2-99' y='201.694'/>
+<use x='184.627' xlink:href='#g2-45' y='201.694'/>
+<use x='187.449' xlink:href='#g2-116' y='201.694'/>
+<use x='190.507' xlink:href='#g2-101' y='201.694'/>
+<use x='194.271' xlink:href='#g2-115' y='201.694'/>
+<use x='197.517' xlink:href='#g2-116' y='201.694'/>
+<use x='200.575' xlink:href='#g2-49' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 61.588)'>
+<use x='168.285' xlink:href='#g2-97' y='201.694'/>
+<use x='172.353' xlink:href='#g2-108' y='201.694'/>
+<use x='174.373' xlink:href='#g2-108' y='201.694'/>
+<use x='176.393' xlink:href='#g2-111' y='201.694'/>
+<use x='180.863' xlink:href='#g2-99' y='201.694'/>
+<use x='184.627' xlink:href='#g2-45' y='201.694'/>
+<use x='187.449' xlink:href='#g2-116' y='201.694'/>
+<use x='190.507' xlink:href='#g2-101' y='201.694'/>
+<use x='194.271' xlink:href='#g2-115' y='201.694'/>
+<use x='197.517' xlink:href='#g2-116' y='201.694'/>
+<use x='200.575' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 61.588)'>
+<use x='168.285' xlink:href='#g2-115' y='201.694'/>
+<use x='171.531' xlink:href='#g2-104' y='201.694'/>
+<use x='175.904' xlink:href='#g2-54' y='201.694'/>
+<use x='180.138' xlink:href='#g2-98' y='201.694'/>
+<use x='184.746' xlink:href='#g2-101' y='201.694'/>
+<use x='188.509' xlink:href='#g2-110' y='201.694'/>
+<use x='192.882' xlink:href='#g2-99' y='201.694'/>
+<use x='196.646' xlink:href='#g2-104' y='201.694'/>
+<use x='201.018' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 61.588)'>
+<use x='168.285' xlink:href='#g2-115' y='201.694'/>
+<use x='171.531' xlink:href='#g2-104' y='201.694'/>
+<use x='175.904' xlink:href='#g2-56' y='201.694'/>
+<use x='180.138' xlink:href='#g2-98' y='201.694'/>
+<use x='184.746' xlink:href='#g2-101' y='201.694'/>
+<use x='188.509' xlink:href='#g2-110' y='201.694'/>
+<use x='192.882' xlink:href='#g2-99' y='201.694'/>
+<use x='196.646' xlink:href='#g2-104' y='201.694'/>
+<use x='201.018' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 61.588)'>
+<use x='168.285' xlink:href='#g2-120' y='201.694'/>
+<use x='172.187' xlink:href='#g2-109' y='201.694'/>
+<use x='178.912' xlink:href='#g2-97' y='201.694'/>
+<use x='182.98' xlink:href='#g2-108' y='201.694'/>
+<use x='185' xlink:href='#g2-108' y='201.694'/>
+<use x='187.02' xlink:href='#g2-111' y='201.694'/>
+<use x='191.49' xlink:href='#g2-99' y='201.694'/>
+<use x='195.254' xlink:href='#g2-45' y='201.694'/>
+<use x='198.076' xlink:href='#g2-116' y='201.694'/>
+<use x='201.134' xlink:href='#g2-101' y='201.694'/>
+<use x='204.898' xlink:href='#g2-115' y='201.694'/>
+<use x='208.144' xlink:href='#g2-116' y='201.694'/>
+<use x='211.202' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 61.588)'>
+<use x='168.285' xlink:href='#g2-99' y='201.694'/>
+<use x='172.049' xlink:href='#g2-97' y='201.694'/>
+<use x='176.117' xlink:href='#g2-99' y='201.694'/>
+<use x='179.88' xlink:href='#g2-104' y='201.694'/>
+<use x='184.253' xlink:href='#g2-101' y='201.694'/>
+<use x='188.017' xlink:href='#g2-45' y='201.694'/>
+<use x='190.839' xlink:href='#g2-115' y='201.694'/>
+<use x='194.086' xlink:href='#g2-99' y='201.694'/>
+<use x='197.849' xlink:href='#g2-114' y='201.694'/>
+<use x='200.741' xlink:href='#g2-97' y='201.694'/>
+<use x='204.81' xlink:href='#g2-116' y='201.694'/>
+<use x='207.868' xlink:href='#g2-99' y='201.694'/>
+<use x='211.631' xlink:href='#g2-104' y='201.694'/>
+<use x='216.004' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 49.223)'>
+<use x='168.285' xlink:href='#g1-48' y='201.694'/>
+<use x='170.931' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.67)'>
+<use x='168.285' xlink:href='#g1-48' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -17.883)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -51.436)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -84.989)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -118.543)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<path clip-path='url(#clip2)' d='M135.949 182.176H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M145.356 249.281H148.594V182.176H145.356ZM204.028 249.281H207.266V182.176H204.028ZM262.695 249.281H265.934V182.176H262.695ZM321.363 249.281H324.602V182.176H321.363ZM380.031 249.281H383.27V182.176H380.031ZM438.703 249.281H441.942V182.176H438.703Z' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M145.356 249.281H148.594V182.176H145.356ZM204.028 249.281H207.266V182.176H204.028ZM262.695 249.281H265.934V182.176H262.695ZM321.363 249.281H324.602V182.176H321.363ZM380.031 249.281H383.27V182.176H380.031ZM438.703 249.281H441.942V182.176H438.703Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M146.977 182.176V182.043' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M146.977 182.176V182.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M144.984 182.043H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M146.977 182.176V182.308' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M146.977 182.176V182.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M148.969 182.308H144.984' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M205.645 182.176V182.043' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M205.645 182.176V182.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M203.652 182.043H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M205.645 182.176V182.308' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M205.645 182.176V182.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M207.636 182.308H203.652' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M264.313 182.176V180.429' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M264.313 182.176V180.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M262.32 180.429H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M264.313 182.176V183.922' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M264.313 182.176V183.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M266.304 183.922H262.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M322.984 182.176V181.504' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M322.984 182.176V181.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M320.992 181.504H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M322.984 182.176V182.847' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M322.984 182.176V182.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M324.976 182.847H320.988' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M381.652 182.176V181.84' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M381.652 182.176V181.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M379.66 181.84H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M381.652 182.176V182.512' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M381.652 182.176V182.512' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M383.644 182.512H379.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M440.32 182.176V181.371' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M440.32 182.176V181.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M438.328 181.371H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M440.32 182.176V182.98' fill='#e0e0f0'/>
+<path clip-path='url(#clip2)' d='M440.32 182.176V182.98' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M442.312 182.98H438.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M150.586 249.281H153.824V180.765H150.586ZM209.258 249.281H212.496V173.117H209.258ZM267.926 249.281H271.164V158.086H267.926ZM326.594 249.281H329.832V81.515H326.594ZM385.262 249.281H388.5V81.515H385.262ZM443.934 249.281H447.172V81.515H443.934Z' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M150.586 249.281H153.824V180.765H150.586ZM209.258 249.281H212.496V173.117H209.258ZM267.926 249.281H271.164V158.086H267.926ZM326.594 249.281H329.832V81.515H326.594ZM385.262 249.281H388.5V81.515H385.262ZM443.934 249.281H447.172V81.515H443.934Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M152.207 180.765V180.633' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M152.207 180.765V180.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M150.215 180.633H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M152.207 180.765V180.902' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M152.207 180.765V180.902' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M154.2 180.902H150.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M210.875 173.117V172.914' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M210.875 173.117V172.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M208.883 172.915H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M210.875 173.117V173.316' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M210.875 173.117V173.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M212.867 173.316H208.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M269.543 158.086V157.48' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M269.543 158.086V157.48' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M267.551 157.48H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M269.543 158.086V158.687' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M269.543 158.086V158.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M271.535 158.687H267.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M328.215 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M326.223 81.516H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M328.215 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M326.223 81.516H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M386.883 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M384.891 81.516H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M386.883 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M384.891 81.516H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M445.551 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M443.559 81.516H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M445.551 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip2)' d='M443.559 81.516H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M155.817 249.281H159.055V175.668H155.817ZM214.488 249.281H217.727V172.648H214.488ZM273.156 249.281H276.395V81.515H273.156ZM331.824 249.281H335.063V148.152H331.824ZM390.492 249.281H393.731V130.57H390.492ZM449.164 249.281H452.402V81.515H449.164Z' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M155.817 249.281H159.055V175.668H155.817ZM214.488 249.281H217.727V172.648H214.488ZM273.156 249.281H276.395V81.515H273.156ZM331.824 249.281H335.063V148.152H331.824ZM390.492 249.281H393.731V130.57H390.492ZM449.164 249.281H452.402V81.515H449.164Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M157.438 175.668V174.39' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M157.438 175.668V174.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M155.445 174.391H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M157.438 175.668V176.941' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M157.438 175.668V176.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M159.43 176.942H155.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M216.106 172.648V172.648' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M214.113 172.648H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M216.106 172.648V172.648' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M214.113 172.648H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M274.774 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M272.781 81.516H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M274.774 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M272.781 81.516H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M333.445 148.152V146.945' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M333.445 148.152V146.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M331.453 146.945H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M333.445 148.152V149.359' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M333.445 148.152V149.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M335.437 149.359H331.449' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M392.113 130.57V129.566' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M392.113 130.57V129.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M390.121 129.566H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M392.113 130.57V131.578' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M392.113 130.57V131.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M394.105 131.578H390.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M450.781 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M448.789 81.516H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M450.781 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip2)' d='M448.789 81.516H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M161.047 249.281H164.285V157.949H161.047ZM219.719 249.281H222.957V144.664H219.719ZM278.387 249.281H281.625V81.515H278.387ZM337.055 249.281H340.293V156.879H337.055ZM395.723 249.281H398.961V162.984H395.723ZM454.395 249.281H457.633V179.426H454.395Z' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M161.047 249.281H164.285V157.949H161.047ZM219.719 249.281H222.957V144.664H219.719ZM278.387 249.281H281.625V81.515H278.387ZM337.055 249.281H340.293V156.879H337.055ZM395.723 249.281H398.961V162.984H395.723ZM454.395 249.281H457.633V179.426H454.395Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M162.668 157.949V157.883' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M162.668 157.949V157.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M160.676 157.883H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M162.668 157.949V158.019' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M162.668 157.949V158.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M164.661 158.02H160.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M221.336 144.664V144.261' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M221.336 144.664V144.261' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M219.344 144.261H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M221.336 144.664V145.066' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M221.336 144.664V145.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M223.329 145.066H219.344' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M280.004 81.515V81.515' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M278.012 81.516H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M280.004 81.515V81.515' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M278.012 81.516H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M338.676 156.879V156.004' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M338.676 156.879V156.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M336.684 156.004H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M338.676 156.879V157.75' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M338.676 156.879V157.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M340.668 157.75H336.68' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M397.344 162.984V162.582' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M397.344 162.984V162.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M395.352 162.582H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M397.344 162.984V163.387' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M397.344 162.984V163.387' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M399.336 163.386H395.352' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M456.012 179.426V178.621' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M456.012 179.426V178.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M454.02 178.622H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M456.012 179.426V180.23' fill='#8585c2'/>
+<path clip-path='url(#clip2)' d='M456.012 179.426V180.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M458.004 180.23H454.02' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M166.278 249.281H169.516V163.992H166.278ZM224.949 249.281H228.188V159.426H224.949ZM283.617 249.281H286.856V91.047H283.617ZM342.285 249.281H345.524V81.515H342.285ZM400.953 249.281H404.192V81.515H400.953ZM459.625 249.281H462.863V81.515H459.625Z' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M166.278 249.281H169.516V163.992H166.278ZM224.949 249.281H228.188V159.426H224.949ZM283.617 249.281H286.856V91.047H283.617ZM342.285 249.281H345.524V81.515H342.285ZM400.953 249.281H404.192V81.515H400.953ZM459.625 249.281H462.863V81.515H459.625Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M167.899 163.992V163.722' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M167.899 163.992V163.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M165.906 163.723H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M167.899 163.992V164.258' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M167.899 163.992V164.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M169.891 164.258H165.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M226.567 159.426V159.359' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M226.567 159.426V159.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M224.574 159.359H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M226.567 159.426V159.496' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M226.567 159.426V159.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M228.559 159.496H224.574' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M285.234 91.047V90.777' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M285.234 91.047V90.777' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M283.242 90.777H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M285.234 91.047V91.316' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M285.234 91.047V91.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M287.227 91.316H283.242' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M343.906 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M341.914 81.516H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M343.906 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M341.914 81.516H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M402.574 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M400.582 81.516H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M402.574 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M400.582 81.516H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M461.242 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M459.25 81.516H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M461.242 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip2)' d='M459.25 81.516H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M171.508 249.281H174.746V172.648H171.508ZM230.18 249.281H233.414V132.519H230.18ZM288.848 249.281H292.086V124.867H288.848ZM347.516 249.281H350.754V81.515H347.516ZM406.184 249.281H409.422V81.515H406.184ZM464.856 249.281H468.094V81.515H464.856Z' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M171.508 249.281H174.746V172.648H171.508ZM230.18 249.281H233.414V132.519H230.18ZM288.848 249.281H292.086V124.867H288.848ZM347.516 249.281H350.754V81.515H347.516ZM406.184 249.281H409.422V81.515H406.184ZM464.856 249.281H468.094V81.515H464.856Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M173.129 172.648V172.312' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M173.129 172.648V172.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M171.137 172.313H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M173.129 172.648V172.984' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M173.129 172.648V172.984' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M175.122 172.985H171.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M231.797 132.519V131.847' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M231.797 132.519V131.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M229.805 131.848H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M231.797 132.519V133.187' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M231.797 132.519V133.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M233.79 133.188H229.805' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M290.465 124.867V124.062' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M290.465 124.867V124.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M288.473 124.062H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M290.465 124.867V125.672' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M290.465 124.867V125.672' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M292.458 125.672H288.473' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M349.137 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M347.145 81.516H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M349.137 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M347.145 81.516H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M407.805 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M405.813 81.516H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M407.805 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M405.813 81.516H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M466.473 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M464.481 81.516H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M466.473 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip2)' d='M464.481 81.516H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M176.738 249.281H179.977V163.656H176.738ZM235.41 249.281H238.645V159.359H235.41ZM294.078 249.281H297.317V90.578H294.078ZM352.746 249.281H355.984V81.515H352.746ZM411.414 249.281H414.652V81.515H411.414ZM470.086 249.281H473.324V81.515H470.086Z' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M176.738 249.281H179.977V163.656H176.738ZM235.41 249.281H238.645V159.359H235.41ZM294.078 249.281H297.317V90.578H294.078ZM352.746 249.281H355.984V81.515H352.746ZM411.414 249.281H414.652V81.515H411.414ZM470.086 249.281H473.324V81.515H470.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M178.36 163.656V163.32' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M178.36 163.656V163.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M176.367 163.32H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M178.36 163.656V163.992' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M178.36 163.656V163.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M180.352 163.992H176.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M237.027 159.359V159.359' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M235.035 159.359H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M237.027 159.359V159.359' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M235.035 159.359H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M295.695 90.578V89.234' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M295.695 90.578V89.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M293.703 89.234H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M295.695 90.578V91.918' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M295.695 90.578V91.918' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M297.688 91.918H293.703' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M354.367 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M352.375 81.516H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M354.367 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M352.375 81.516H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M413.035 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M411.043 81.516H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M413.035 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M411.043 81.516H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M471.703 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M469.711 81.516H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M471.703 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip2)' d='M469.711 81.516H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M416.645 249.281H419.883V131.445H416.645ZM181.969 249.281H185.207V153.523H181.969ZM240.641 249.281H243.875V149.226H240.641ZM299.309 249.281H302.547V81.515H299.309ZM357.977 249.281H361.215V129.297H357.977ZM475.317 249.281H478.555V179.894H475.317Z' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M416.645 249.281H419.883V131.445H416.645ZM181.969 249.281H185.207V153.523H181.969ZM240.641 249.281H243.875V149.226H240.641ZM299.309 249.281H302.547V81.515H299.309ZM357.977 249.281H361.215V129.297H357.977ZM475.317 249.281H478.555V179.894H475.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M418.266 131.445V128.894' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M418.266 131.445V128.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M416.274 128.895H420.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M418.266 131.445V133.992' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M418.266 131.445V133.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M420.257 133.992H416.273' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M183.59 153.523V152.851' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M183.59 153.523V152.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M181.598 152.852H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M183.59 153.523V154.191' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M183.59 153.523V154.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M185.582 154.191H181.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M242.258 149.226V149.16' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M242.258 149.226V149.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M240.266 149.16H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M242.258 149.226V149.293' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M242.258 149.226V149.293' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M244.25 149.293H240.265' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M300.926 81.515V81.515' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M298.933 81.516H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M300.926 81.515V81.515' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M298.933 81.516H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M359.598 129.297V128.426' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M359.598 129.297V128.426' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M357.606 128.426H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M359.598 129.297V130.168' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M359.598 129.297V130.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M361.589 130.168H357.601' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M476.934 179.894V179.894' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M474.942 179.895H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M476.934 179.894V179.894' fill='#0a0a85'/>
+<path clip-path='url(#clip2)' d='M474.942 179.895H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip2)' d='M418.387 298.301H487.762V276.324H418.387Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 253.422 92.648)'>
+<use x='168.285' xlink:href='#g1-114' y='190.457'/>
+<use x='170.092' xlink:href='#g1-53' y='190.457'/>
+<use x='172.739' xlink:href='#g1-97' y='190.457'/>
+<use x='175.281' xlink:href='#g1-45' y='190.457'/>
+<use x='177.046' xlink:href='#g1-52' y='190.457'/>
+<use x='179.692' xlink:href='#g1-120' y='190.457'/>
+<use x='182.131' xlink:href='#g1-108' y='190.457'/>
+<use x='183.393' xlink:href='#g1-97' y='190.457'/>
+<use x='185.789' xlink:href='#g1-114' y='190.457'/>
+<use x='187.596' xlink:href='#g1-103' y='190.457'/>
+<use x='190.243' xlink:href='#g1-101' y='190.457'/>
+<use x='192.595' xlink:href='#g1-44' y='190.457'/>
+<use x='195.83' xlink:href='#g1-49' y='190.457'/>
+<use x='198.476' xlink:href='#g1-50' y='190.457'/>
+<use x='201.122' xlink:href='#g1-56' y='190.457'/>
+<use x='203.769' xlink:href='#g1-71' y='190.457'/>
+<use x='207.297' xlink:href='#g1-98' y='190.457'/>
+<use x='168.285' xlink:href='#g1-49' y='196.075'/>
+<use x='170.931' xlink:href='#g1-54' y='196.075'/>
+<use x='173.578' xlink:href='#g1-45' y='196.075'/>
+<use x='175.342' xlink:href='#g1-99' y='196.075'/>
+<use x='177.694' xlink:href='#g1-111' y='196.075'/>
+<use x='180.193' xlink:href='#g1-114' y='196.075'/>
+<use x='182.001' xlink:href='#g1-101' y='196.075'/>
+<use x='186.118' xlink:href='#g1-65' y='196.075'/>
+<use x='189.646' xlink:href='#g1-77' y='196.075'/>
+<use x='194.264' xlink:href='#g1-68' y='196.075'/>
+<use x='199.851' xlink:href='#g1-69' y='196.075'/>
+<use x='203.025' xlink:href='#g1-112' y='196.075'/>
+<use x='205.611' xlink:href='#g1-121' y='196.075'/>
+<use x='208.049' xlink:href='#g1-99' y='196.075'/>
+<use x='212.166' xlink:href='#g1-64' y='196.075'/>
+<use x='215.695' xlink:href='#g1-50' y='196.075'/>
+<use x='218.341' xlink:href='#g1-46' y='196.075'/>
+<use x='219.811' xlink:href='#g1-53' y='196.075'/>
+<use x='222.457' xlink:href='#g1-71' y='196.075'/>
+<use x='225.986' xlink:href='#g1-104' y='196.075'/>
+<use x='228.719' xlink:href='#g1-122' y='196.075'/>
+<use x='168.285' xlink:href='#g1-85' y='201.694'/>
+<use x='171.917' xlink:href='#g1-98' y='201.694'/>
+<use x='174.65' xlink:href='#g1-117' y='201.694'/>
+<use x='177.383' xlink:href='#g1-110' y='201.694'/>
+<use x='180.116' xlink:href='#g1-116' y='201.694'/>
+<use x='182.027' xlink:href='#g1-117' y='201.694'/>
+<use x='186.524' xlink:href='#g1-49' y='201.694'/>
+<use x='189.17' xlink:href='#g1-56' y='201.694'/>
+<use x='191.817' xlink:href='#g1-46' y='201.694'/>
+<use x='193.287' xlink:href='#g1-48' y='201.694'/>
+<use x='195.933' xlink:href='#g1-52' y='201.694'/>
+<use x='198.58' xlink:href='#g1-46' y='201.694'/>
+<use x='200.05' xlink:href='#g1-49' y='201.694'/>
+<use x='202.696' xlink:href='#g1-44' y='201.694'/>
+<use x='205.931' xlink:href='#g1-71' y='201.694'/>
+<use x='209.459' xlink:href='#g1-67' y='201.694'/>
+<use x='212.841' xlink:href='#g1-67' y='201.694'/>
+<use x='217.986' xlink:href='#g1-55' y='201.694'/>
+<use x='220.633' xlink:href='#g1-46' y='201.694'/>
+<use x='222.103' xlink:href='#g1-51' y='201.694'/>
+<use x='224.749' xlink:href='#g1-46' y='201.694'/>
+<use x='226.219' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -53.084 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 5.585 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.254 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 122.923 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 181.592 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.261 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -47.853 342.848)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-50' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 10.816 335.198)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 69.485 320.166)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.154 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-56' y='201.694'/>
+<use x='180.675' xlink:href='#g1-50' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 186.823 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-56' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-50' y='201.694'/>
+<use x='180.675' xlink:href='#g1-50' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 245.492 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-57' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-50' y='201.694'/>
+<use x='183.321' xlink:href='#g1-51' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -42.623 337.748)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 16.046 334.728)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.715 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-56' y='201.694'/>
+<use x='180.675' xlink:href='#g1-51' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.384 310.234)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 192.053 292.653)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-55' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 250.722 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-56' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-48' y='201.694'/>
+<use x='183.321' xlink:href='#g1-57' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -37.392 320.032)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.277 306.745)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.946 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-55' y='201.694'/>
+<use x='180.675' xlink:href='#g1-52' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.615 318.958)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-56' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.284 325.065)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-57' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 255.953 341.506)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.162 326.071)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-55' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.507 321.508)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.176 253.127)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.845 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-57' y='201.694'/>
+<use x='180.675' xlink:href='#g1-52' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.514 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-50' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-53' y='201.694'/>
+<use x='183.321' xlink:href='#g1-50' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.183 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-52' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-50' y='201.694'/>
+<use x='180.675' xlink:href='#g1-49' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -26.931 334.728)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.738 294.599)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.407 286.949)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-56' y='201.694'/>
+<use x='175.048' xlink:href='#g1-53' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 149.076 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-52' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-55' y='201.694'/>
+<use x='180.675' xlink:href='#g1-51' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.745 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-51' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-53' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 266.414 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-57' y='201.694'/>
+<use x='180.675' xlink:href='#g1-53' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -21.701 325.736)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-56' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.968 321.441)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.637 252.657)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-55' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 154.306 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-57' y='201.694'/>
+<use x='180.675' xlink:href='#g1-55' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.975 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-49' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-55' y='201.694'/>
+<use x='183.321' xlink:href='#g1-56' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 271.644 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-52' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-49' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 218.205 293.525)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.471 315.603)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-51' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 42.198 311.308)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-57' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.867 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-52' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.536 291.377)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-57' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 276.874 341.975)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-51' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -88.536 388.944)'>
+<use x='168.285' xlink:href='#g0-82' y='201.694'/>
+<use x='174.255' xlink:href='#g0-101' y='201.694'/>
+<use x='178.351' xlink:href='#g0-108' y='201.694'/>
+<use x='180.551' xlink:href='#g0-97' y='201.694'/>
+<use x='184.979' xlink:href='#g0-116' y='201.694'/>
+<use x='188.307' xlink:href='#g0-105' y='201.694'/>
+<use x='190.507' xlink:href='#g0-118' y='201.694'/>
+<use x='194.755' xlink:href='#g0-101' y='201.694'/>
+<use x='201.922' xlink:href='#g0-116' y='201.694'/>
+<use x='205.25' xlink:href='#g0-105' y='201.694'/>
+<use x='207.45' xlink:href='#g0-109' y='201.694'/>
+<use x='214.77' xlink:href='#g0-101' y='201.694'/>
+<use x='221.937' xlink:href='#g2-40' y='201.694'/>
+<use x='225.231' xlink:href='#g2-108' y='201.694'/>
+<use x='227.251' xlink:href='#g2-111' y='201.694'/>
+<use x='231.25' xlink:href='#g2-119' y='201.694'/>
+<use x='236.799' xlink:href='#g2-101' y='201.694'/>
+<use x='240.562' xlink:href='#g2-114' y='201.694'/>
+<use x='246.277' xlink:href='#g2-105' y='201.694'/>
+<use x='248.297' xlink:href='#g2-115' y='201.694'/>
+<use x='254.366' xlink:href='#g2-98' y='201.694'/>
+<use x='258.974' xlink:href='#g2-101' y='201.694'/>
+<use x='262.738' xlink:href='#g2-116' y='201.694'/>
+<use x='265.796' xlink:href='#g2-116' y='201.694'/>
+<use x='268.854' xlink:href='#g2-101' y='201.694'/>
+<use x='272.618' xlink:href='#g2-114' y='201.694'/>
+<use x='275.51' xlink:href='#g2-41' y='201.694'/>
+</g>
+<path d='M136.149 296.672H349.488V279.679H136.149Z' fill='#ffffff'/>
+<path d='M136.149 296.672H349.488V279.679H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='#e0e0f0'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 88.465)'>
+<use x='185.011' xlink:href='#g2-109' y='201.694'/>
+<use x='191.736' xlink:href='#g2-105' y='201.694'/>
+</g>
+<path d='M163.422 290.168H166.41V282.199H163.422ZM169.398 290.168H172.391V284.191H169.398Z' fill='#c2c2e1'/>
+<path d='M163.422 290.168H166.41V282.199H163.422ZM169.398 290.168H172.391V284.191H169.398Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 88.011)'>
+<use x='208.137' xlink:href='#g2-116' y='201.694'/>
+<use x='211.195' xlink:href='#g2-99' y='201.694'/>
+</g>
+<path d='M185.586 290.168H188.574V282.199H185.586ZM191.563 290.168H194.555V284.191H191.563Z' fill='#a3a3d1'/>
+<path d='M185.586 290.168H188.574V282.199H185.586ZM191.563 290.168H194.555V284.191H191.563Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 88.465)'>
+<use x='229.9' xlink:href='#g2-106' y='201.694'/>
+<use x='232.155' xlink:href='#g2-101' y='201.694'/>
+</g>
+<path d='M206.949 290.168H209.938V282.199H206.949ZM212.926 290.168H215.914V284.191H212.926Z' fill='#8585c2'/>
+<path d='M206.949 290.168H209.938V282.199H206.949ZM212.926 290.168H215.914V284.191H212.926Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 87.505)'>
+<use x='252.061' xlink:href='#g2-115' y='201.694'/>
+<use x='255.307' xlink:href='#g2-110' y='201.694'/>
+</g>
+<path d='M229.91 290.168H232.898V282.199H229.91ZM235.887 290.168H238.875V284.191H235.887Z' fill='#6666b3'/>
+<path d='M229.91 290.168H232.898V282.199H229.91ZM235.887 290.168H238.875V284.191H235.887Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 87.505)'>
+<use x='274.845' xlink:href='#g2-114' y='201.694'/>
+<use x='277.737' xlink:href='#g2-112' y='201.694'/>
+</g>
+<path d='M252.516 290.168H255.504V282.199H252.516ZM258.496 290.168H261.484V284.191H258.496Z' fill='#4747a4'/>
+<path d='M252.516 290.168H255.504V282.199H252.516ZM258.496 290.168H261.484V284.191H258.496Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 88.501)'>
+<use x='303.672' xlink:href='#g2-104' y='201.694'/>
+<use x='308.045' xlink:href='#g2-111' y='201.694'/>
+<use x='312.279' xlink:href='#g2-97' y='201.694'/>
+<use x='316.112' xlink:href='#g2-114' y='201.694'/>
+<use x='319.004' xlink:href='#g2-100' y='201.694'/>
+</g>
+<path d='M287.563 290.168H290.551V282.199H287.563ZM293.543 290.168H296.531V284.191H293.543Z' fill='#292994'/>
+<path d='M287.563 290.168H290.551V282.199H287.563ZM293.543 290.168H296.531V284.191H293.543Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 88.501)'>
+<use x='337.19' xlink:href='#g2-103' y='201.694'/>
+<use x='341.424' xlink:href='#g2-108' y='201.694'/>
+<use x='343.444' xlink:href='#g2-105' y='201.694'/>
+<use x='345.464' xlink:href='#g2-98' y='201.694'/>
+<use x='350.072' xlink:href='#g2-99' y='201.694'/>
+</g>
+<path d='M319.551 290.168H322.539V282.199H319.551ZM325.527 290.168H328.52V284.191H325.527Z' fill='#0a0a85'/>
+<path d='M319.551 290.168H322.539V282.199H319.551ZM325.527 290.168H328.52V284.191H325.527Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 88.501)'>
+<use x='366.757' xlink:href='#g2-116' y='201.694'/>
+<use x='369.815' xlink:href='#g2-98' y='201.694'/>
+<use x='374.187' xlink:href='#g2-98' y='201.694'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg
new file mode 100644 (file)
index 0000000..375ebd2
--- /dev/null
@@ -0,0 +1,683 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='164.687pt' version='1.1' viewBox='52.938 54.996 381.625 164.687' width='381.625pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip7'>
+<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-102' transform='scale(1.6)' xlink:href='#g1-102'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M0.946 -1.898H1.514V-2.212H0.932V-2.785C0.932 -3.128 1.245 -3.178 1.41 -3.178C1.514 -3.178 1.649 -3.163 1.833 -3.093V-3.457C1.704 -3.487 1.549 -3.507 1.415 -3.507C0.902 -3.507 0.528 -3.138 0.528 -2.645V-2.212H0.144V-1.898H0.528V0H0.946V-1.898Z' id='g1-102'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g0-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g0-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page7'>
+<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 33.989)'>
+<use x='114.487' xlink:href='#g2-99' y='183.949'/>
+<use x='118.25' xlink:href='#g2-102' y='183.949'/>
+<use x='120.838' xlink:href='#g2-114' y='183.949'/>
+<use x='123.73' xlink:href='#g2-97' y='183.949'/>
+<use x='127.798' xlink:href='#g2-99' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 41.401 33.989)'>
+<use x='114.487' xlink:href='#g2-101' y='183.949'/>
+<use x='118.25' xlink:href='#g2-115' y='183.949'/>
+<use x='121.497' xlink:href='#g2-112' y='183.949'/>
+<use x='125.634' xlink:href='#g2-114' y='183.949'/>
+<use x='128.526' xlink:href='#g2-101' y='183.949'/>
+<use x='132.29' xlink:href='#g2-115' y='183.949'/>
+<use x='135.536' xlink:href='#g2-115' y='183.949'/>
+<use x='138.782' xlink:href='#g2-111' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 103.095 33.989)'>
+<use x='114.487' xlink:href='#g2-98' y='183.949'/>
+<use x='118.859' xlink:href='#g2-97' y='183.949'/>
+<use x='122.692' xlink:href='#g2-114' y='183.949'/>
+<use x='125.584' xlink:href='#g2-110' y='183.949'/>
+<use x='129.957' xlink:href='#g2-101' y='183.949'/>
+<use x='133.72' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 162.903 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-101' y='183.949'/>
+<use x='120.271' xlink:href='#g2-97' y='183.949'/>
+<use x='124.339' xlink:href='#g2-110' y='183.949'/>
+<use x='128.711' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 223.526 33.989)'>
+<use x='114.487' xlink:href='#g2-114' y='183.949'/>
+<use x='117.379' xlink:href='#g2-101' y='183.949'/>
+<use x='121.142' xlink:href='#g2-100' y='183.949'/>
+<use x='125.515' xlink:href='#g2-105' y='183.949'/>
+<use x='127.535' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 277.054 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-97' y='183.949'/>
+<use x='120.34' xlink:href='#g2-114' y='183.949'/>
+<use x='123.232' xlink:href='#g2-115' y='183.949'/>
+<use x='126.478' xlink:href='#g2-111' y='183.949'/>
+<use x='130.712' xlink:href='#g2-110' y='183.949'/>
+<use x='135.085' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 21.624)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.688)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.999)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -72.311)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.622)'>
+<use x='114.487' xlink:href='#g1-50' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<path clip-path='url(#clip7)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M91.559 203.937H94.797V141.316H91.559ZM150.227 203.937H153.465V141.316H150.227ZM208.899 203.937H212.133V141.316H208.899ZM267.567 203.937H270.805V141.316H267.567ZM326.234 203.937H329.473V141.316H326.234ZM384.902 203.937H388.141V141.316H384.902Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M91.559 203.937H94.797V141.316H91.559ZM150.227 203.937H153.465V141.316H150.227ZM208.899 203.937H212.133V141.316H208.899ZM267.567 203.937H270.805V141.316H267.567ZM326.234 203.937H329.473V141.316H326.234ZM384.902 203.937H388.141V141.316H384.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M93.18 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M91.184 141.316H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M93.18 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M91.184 141.316H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M151.848 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M149.855 141.316H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M151.848 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M149.855 141.316H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M210.516 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M208.523 141.316H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M210.516 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M208.523 141.316H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M269.184 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M267.191 141.316H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M269.184 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M267.191 141.316H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M327.856 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M325.859 141.316H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M327.856 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M325.859 141.316H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M386.524 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M384.531 141.316H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M386.524 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip7)' d='M384.531 141.316H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M96.789 203.937H100.027V94.222H96.789ZM155.457 203.937H158.695V78.691H155.457ZM214.129 203.937H217.363V138.246H214.129ZM272.797 203.937H276.035V154.652H272.797ZM331.465 203.937H334.703V129.793H331.465ZM390.133 203.937H393.371V138.808H390.133Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M96.789 203.937H100.027V94.222H96.789ZM155.457 203.937H158.695V78.691H155.457ZM214.129 203.937H217.363V138.246H214.129ZM272.797 203.937H276.035V154.652H272.797ZM331.465 203.937H334.703V129.793H331.465ZM390.133 203.937H393.371V138.808H390.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M98.41 94.222V94.222' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M96.414 94.223H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M98.41 94.222V94.222' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M96.414 94.223H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M157.078 78.691V78.691' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M155.086 78.691H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M157.078 78.691V78.691' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M155.086 78.691H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M215.746 138.246V138.246' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M213.754 138.246H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M215.746 138.246V138.246' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M213.754 138.246H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M274.414 154.652V154.652' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M272.422 154.652H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M274.414 154.652V154.652' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M272.422 154.652H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M333.086 129.793V129.793' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M331.09 129.793H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M333.086 129.793V129.793' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M331.09 129.793H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M391.754 138.808V138.808' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M389.762 138.808H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M391.754 138.808V138.808' fill='#e1c2e1'/>
+<path clip-path='url(#clip7)' d='M389.762 138.808H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M102.02 203.937H105.258V115.828H102.02ZM160.688 203.937H163.926V108.187H160.688ZM219.359 203.937H222.594V139.625H219.359ZM278.027 203.937H281.266V141.379H278.027ZM336.695 203.937H339.934V137.246H336.695ZM395.363 203.937H398.602V122.09H395.363Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M102.02 203.937H105.258V115.828H102.02ZM160.688 203.937H163.926V108.187H160.688ZM219.359 203.937H222.594V139.625H219.359ZM278.027 203.937H281.266V141.379H278.027ZM336.695 203.937H339.934V137.246H336.695ZM395.363 203.937H398.602V122.09H395.363Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M103.641 115.828V115.828' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M101.644 115.828H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M103.641 115.828V115.828' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M101.644 115.828H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M162.309 108.187V108.187' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M160.316 108.188H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M162.309 108.187V108.187' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M160.316 108.188H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M220.977 139.625V139.625' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M218.984 139.625H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M220.977 139.625V139.625' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M218.984 139.625H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M279.645 141.379V141.379' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M277.652 141.379H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M279.645 141.379V141.379' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M277.652 141.379H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M338.317 137.246V137.246' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M336.32 137.246H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M338.317 137.246V137.246' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M336.32 137.246H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M396.984 122.09V122.09' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M394.992 122.09H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M396.984 122.09V122.09' fill='#d1a3d1'/>
+<path clip-path='url(#clip7)' d='M394.992 122.09H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M107.25 203.937H110.488V123.469H107.25ZM165.918 203.937H169.156V112.133H165.918ZM224.59 203.937H227.824V140.187H224.59ZM283.258 203.937H286.496V140.312H283.258ZM341.926 203.937H345.164V137.933H341.926ZM400.594 203.937H403.832V126.347H400.594Z' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M107.25 203.937H110.488V123.469H107.25ZM165.918 203.937H169.156V112.133H165.918ZM224.59 203.937H227.824V140.187H224.59ZM283.258 203.937H286.496V140.312H283.258ZM341.926 203.937H345.164V137.933H341.926ZM400.594 203.937H403.832V126.347H400.594Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M108.871 123.469V123.469' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M106.875 123.469H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M108.871 123.469V123.469' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M106.875 123.469H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M167.539 112.133V112.133' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M165.547 112.133H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M167.539 112.133V112.133' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M165.547 112.133H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M226.207 140.187V140.187' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M224.215 140.187H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M226.207 140.187V140.187' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M224.215 140.187H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M284.875 140.312V140.312' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M282.883 140.312H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M284.875 140.312V140.312' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M282.883 140.312H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M343.547 137.933V137.933' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M341.551 137.934H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M343.547 137.933V137.933' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M341.551 137.934H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M402.215 126.347V126.347' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M400.223 126.347H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M402.215 126.347V126.347' fill='#c285c2'/>
+<path clip-path='url(#clip7)' d='M400.223 126.347H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M112.481 203.937H115.719V139H112.481ZM171.149 203.937H174.387V143.82H171.149ZM229.82 203.937H233.055V141.316H229.82ZM288.488 203.937H291.727V133.176H288.488ZM347.156 203.937H350.395V140H347.156ZM405.824 203.937H409.063V133.176H405.824Z' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M112.481 203.937H115.719V139H112.481ZM171.149 203.937H174.387V143.82H171.149ZM229.82 203.937H233.055V141.316H229.82ZM288.488 203.937H291.727V133.176H288.488ZM347.156 203.937H350.395V140H347.156ZM405.824 203.937H409.063V133.176H405.824Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M114.098 139V139' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M112.105 139H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M114.098 139V139' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M112.105 139H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M172.77 143.82V143.82' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M170.777 143.82H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M172.77 143.82V143.82' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M170.777 143.82H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M231.438 141.316V141.316' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M229.445 141.316H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M231.438 141.316V141.316' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M229.445 141.316H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M290.106 133.176V133.176' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M288.113 133.176H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M290.106 133.176V133.176' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M288.113 133.176H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M348.777 140V140' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M346.781 140H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M348.777 140V140' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M346.781 140H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M407.445 133.176V133.176' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M405.453 133.176H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M407.445 133.176V133.176' fill='#b366b3'/>
+<path clip-path='url(#clip7)' d='M405.453 133.176H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M117.711 203.937H120.949V111.32H117.711ZM176.379 203.937H179.617V78.691H176.379ZM235.051 203.937H238.285V139.75H235.051ZM293.719 203.937H296.957V125.785H293.719ZM352.387 203.937H355.625V124.906H352.387ZM411.055 203.937H414.293V132.359H411.055Z' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M117.711 203.937H120.949V111.32H117.711ZM176.379 203.937H179.617V78.691H176.379ZM235.051 203.937H238.285V139.75H235.051ZM293.719 203.937H296.957V125.785H293.719ZM352.387 203.937H355.625V124.906H352.387ZM411.055 203.937H414.293V132.359H411.055Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M119.328 111.32V111.32' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M117.336 111.32H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M119.328 111.32V111.32' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M117.336 111.32H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M178 78.691V78.691' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M176.008 78.691H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M178 78.691V78.691' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M176.008 78.691H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M236.668 139.75V139.75' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M234.676 139.75H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M236.668 139.75V139.75' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M234.676 139.75H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M295.336 125.785V125.785' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M293.344 125.785H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M295.336 125.785V125.785' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M293.344 125.785H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M354.008 124.906V124.906' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M352.012 124.906H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M354.008 124.906V124.906' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M352.012 124.906H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M412.676 132.359V132.359' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M410.684 132.359H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M412.676 132.359V132.359' fill='#a447a4'/>
+<path clip-path='url(#clip7)' d='M410.684 132.359H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M122.941 203.937H126.18V143.57H122.941ZM181.609 203.937H184.848V154.34H181.609ZM240.281 203.937H243.516V141.504H240.281ZM298.949 203.937H302.188V133.363H298.949ZM357.617 203.937H360.856V139.937H357.617ZM416.285 203.937H419.524V133.426H416.285Z' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M122.941 203.937H126.18V143.57H122.941ZM181.609 203.937H184.848V154.34H181.609ZM240.281 203.937H243.516V141.504H240.281ZM298.949 203.937H302.188V133.363H298.949ZM357.617 203.937H360.856V139.937H357.617ZM416.285 203.937H419.524V133.426H416.285Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M124.559 143.57V143.57' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M122.566 143.571H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M124.559 143.57V143.57' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M122.566 143.571H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M183.231 154.34V154.34' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M181.238 154.34H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M183.231 154.34V154.34' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M181.238 154.34H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M241.899 141.504V141.504' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M239.906 141.504H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M241.899 141.504V141.504' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M239.906 141.504H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M300.567 133.363V133.363' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M298.574 133.363H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M300.567 133.363V133.363' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M298.574 133.363H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M359.238 139.937V139.937' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M357.242 139.938H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M359.238 139.937V139.937' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M357.242 139.938H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M417.906 133.426V133.426' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M415.914 133.426H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M417.906 133.426V133.426' fill='#942994'/>
+<path clip-path='url(#clip7)' d='M415.914 133.426H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M128.172 203.937H131.41V118.457H128.172ZM186.84 203.937H190.078V113.699H186.84ZM245.512 203.937H248.746V140.062H245.512ZM304.18 203.937H307.418V133.613H304.18ZM362.848 203.937H366.086V97.101H362.848ZM421.516 203.937H424.754V137.371H421.516Z' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M128.172 203.937H131.41V118.457H128.172ZM186.84 203.937H190.078V113.699H186.84ZM245.512 203.937H248.746V140.062H245.512ZM304.18 203.937H307.418V133.613H304.18ZM362.848 203.937H366.086V97.101H362.848ZM421.516 203.937H424.754V137.371H421.516Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M129.789 118.457V118.457' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M127.797 118.457H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M129.789 118.457V118.457' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M127.797 118.457H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M188.461 113.699V113.699' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M186.469 113.7H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M188.461 113.699V113.699' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M186.469 113.7H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M247.129 140.062V140.062' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M245.137 140.063H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M247.129 140.062V140.062' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M245.137 140.063H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M305.797 133.613V133.613' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M303.804 133.614H307.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M305.797 133.613V133.613' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M303.804 133.614H307.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M364.469 97.101V97.101' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M362.473 97.102H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M364.469 97.101V97.101' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M362.473 97.102H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M423.137 137.371V137.371' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M421.144 137.371H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip7)' d='M423.137 137.371V137.371' fill='#850a85'/>
+<path clip-path='url(#clip7)' d='M421.144 137.371H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -89.137 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.468 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.201 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.87 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.539 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.208 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.906 202.685)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.237 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-48' y='183.949'/>
+<use x='126.877' xlink:href='#g1-55' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.432 246.709)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.101 263.116)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.77 238.255)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.439 247.273)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.676 224.29)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -20.007 216.65)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 38.662 248.087)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.331 249.84)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 156 245.707)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 214.669 230.552)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -73.445 231.93)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.776 220.595)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 43.893 248.65)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 102.562 248.776)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.231 246.396)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 219.9 234.811)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -68.215 247.46)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.546 252.282)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.123 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 107.792 241.637)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.461 248.462)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.13 241.637)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.984 219.781)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -4.315 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-52' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-51' y='183.949'/>
+<use x='126.877' xlink:href='#g1-54' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.354 248.212)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.023 234.247)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 171.692 233.37)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.361 240.822)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.754 252.032)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.915 262.803)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.584 249.965)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.253 241.824)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.922 248.4)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.591 241.887)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.524 226.92)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.145 222.161)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.814 248.525)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.483 242.075)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.152 205.566)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.821 245.832)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -124.589 307.697)'>
+<use x='114.487' xlink:href='#g0-82' y='183.949'/>
+<use x='120.457' xlink:href='#g0-101' y='183.949'/>
+<use x='124.553' xlink:href='#g0-108' y='183.949'/>
+<use x='126.753' xlink:href='#g0-97' y='183.949'/>
+<use x='131.181' xlink:href='#g0-116' y='183.949'/>
+<use x='134.509' xlink:href='#g0-105' y='183.949'/>
+<use x='136.709' xlink:href='#g0-118' y='183.949'/>
+<use x='140.957' xlink:href='#g0-101' y='183.949'/>
+<use x='148.124' xlink:href='#g0-114' y='183.949'/>
+<use x='151.272' xlink:href='#g0-115' y='183.949'/>
+<use x='154.805' xlink:href='#g0-115' y='183.949'/>
+<use x='161.409' xlink:href='#g2-40' y='183.949'/>
+<use x='164.702' xlink:href='#g2-108' y='183.949'/>
+<use x='166.722' xlink:href='#g2-111' y='183.949'/>
+<use x='170.721' xlink:href='#g2-119' y='183.949'/>
+<use x='176.27' xlink:href='#g2-101' y='183.949'/>
+<use x='180.034' xlink:href='#g2-114' y='183.949'/>
+<use x='185.749' xlink:href='#g2-105' y='183.949'/>
+<use x='187.769' xlink:href='#g2-115' y='183.949'/>
+<use x='193.838' xlink:href='#g2-98' y='183.949'/>
+<use x='198.446' xlink:href='#g2-101' y='183.949'/>
+<use x='202.209' xlink:href='#g2-116' y='183.949'/>
+<use x='205.267' xlink:href='#g2-116' y='183.949'/>
+<use x='208.325' xlink:href='#g2-101' y='183.949'/>
+<use x='212.089' xlink:href='#g2-114' y='183.949'/>
+<use x='214.981' xlink:href='#g2-41' y='183.949'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg b/extlib/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg
new file mode 100644 (file)
index 0000000..cb2bbc8
--- /dev/null
@@ -0,0 +1,854 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='196.567pt' version='1.1' viewBox='106.737 54.996 381.623 196.567' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip8'>
+<path d='M135.949 203.938H487.961V78.692H135.949Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-45' transform='scale(1.6)' xlink:href='#g1-45'/>
+<use id='g2-49' transform='scale(1.6)' xlink:href='#g1-49'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M2.002 -3.457H1.519L0.149 0H0.558L0.946 -0.986H2.461L2.849 0H3.372L2.002 -3.457ZM1.709 -3.078L2.336 -1.28H1.071L1.709 -3.078Z' id='g1-65'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M0.488 -3.457V0H1.903C2.8 0 3.522 -0.757 3.522 -1.699C3.522 -2.675 2.795 -3.457 1.903 -3.457H0.488ZM0.976 -0.294V-3.163H1.768C2.451 -3.163 3.034 -2.62 3.034 -1.704C3.034 -0.777 2.426 -0.294 1.768 -0.294H0.976Z' id='g1-68'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M2.775 -1.729C2.715 -1.579 2.356 -0.702 2.306 -0.493H2.301C2.267 -0.638 2.037 -1.21 1.988 -1.34L1.131 -3.457H0.523V0H0.941V-3.059H0.946C0.986 -2.884 1.245 -2.227 1.27 -2.172L2.102 -0.105H2.496L3.238 -1.938C3.238 -1.943 3.582 -2.79 3.666 -3.064H3.671V0H4.09V-3.457H3.477L2.775 -1.729Z' id='g1-77'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.361 -2.212H1.958C1.554 -1.26 1.275 -0.618 1.255 -0.314C1.245 -0.453 1.156 -0.702 1.066 -0.936C0.986 -1.136 0.907 -1.335 0.817 -1.529L0.503 -2.212H0.075L1.106 0C1.046 0.144 0.946 0.374 0.917 0.438C0.812 0.648 0.742 0.717 0.608 0.717C0.588 0.717 0.403 0.717 0.189 0.628L0.219 0.976C0.264 0.986 0.448 1.016 0.603 1.016C0.802 1.016 0.981 0.941 1.191 0.463L2.361 -2.212Z' id='g1-121'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g0-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g0-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page8'>
+<path d='M194.617 212.793V203.938M253.285 212.793V203.938M311.953 212.793V203.938M370.625 212.793V203.938M429.293 212.793V203.938M194.617 69.836V78.692M253.285 69.836V78.692M311.953 69.836V78.692M370.625 69.836V78.692M429.293 69.836V78.692' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 208.192V203.938M223.953 208.192V203.938M282.621 208.192V203.938M341.289 208.192V203.938M399.957 208.192V203.938M458.629 208.192V203.938M165.281 74.442V78.692M223.953 74.442V78.692M282.621 74.442V78.692M341.289 74.442V78.692M399.957 74.442V78.692M458.629 74.442V78.692' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 203.938H140.199M135.949 172.625H140.199M135.949 141.317H140.199M135.949 110.004H140.199M135.949 78.692H140.199M487.961 203.938H483.711M487.961 172.625H483.711M487.961 141.317H483.711M487.961 110.004H483.711M487.961 78.692H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 203.938V78.692H487.961V203.938H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 59.571)'>
+<use x='168.285' xlink:href='#g2-97' y='158.367'/>
+<use x='172.353' xlink:href='#g2-108' y='158.367'/>
+<use x='174.373' xlink:href='#g2-108' y='158.367'/>
+<use x='176.393' xlink:href='#g2-111' y='158.367'/>
+<use x='180.863' xlink:href='#g2-99' y='158.367'/>
+<use x='184.627' xlink:href='#g2-45' y='158.367'/>
+<use x='187.449' xlink:href='#g2-116' y='158.367'/>
+<use x='190.507' xlink:href='#g2-101' y='158.367'/>
+<use x='194.271' xlink:href='#g2-115' y='158.367'/>
+<use x='197.517' xlink:href='#g2-116' y='158.367'/>
+<use x='200.575' xlink:href='#g2-49' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 59.571)'>
+<use x='168.285' xlink:href='#g2-97' y='158.367'/>
+<use x='172.353' xlink:href='#g2-108' y='158.367'/>
+<use x='174.373' xlink:href='#g2-108' y='158.367'/>
+<use x='176.393' xlink:href='#g2-111' y='158.367'/>
+<use x='180.863' xlink:href='#g2-99' y='158.367'/>
+<use x='184.627' xlink:href='#g2-45' y='158.367'/>
+<use x='187.449' xlink:href='#g2-116' y='158.367'/>
+<use x='190.507' xlink:href='#g2-101' y='158.367'/>
+<use x='194.271' xlink:href='#g2-115' y='158.367'/>
+<use x='197.517' xlink:href='#g2-116' y='158.367'/>
+<use x='200.575' xlink:href='#g2-78' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 59.571)'>
+<use x='168.285' xlink:href='#g2-115' y='158.367'/>
+<use x='171.531' xlink:href='#g2-104' y='158.367'/>
+<use x='175.904' xlink:href='#g2-54' y='158.367'/>
+<use x='180.138' xlink:href='#g2-98' y='158.367'/>
+<use x='184.746' xlink:href='#g2-101' y='158.367'/>
+<use x='188.509' xlink:href='#g2-110' y='158.367'/>
+<use x='192.882' xlink:href='#g2-99' y='158.367'/>
+<use x='196.646' xlink:href='#g2-104' y='158.367'/>
+<use x='201.018' xlink:href='#g2-78' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 59.571)'>
+<use x='168.285' xlink:href='#g2-115' y='158.367'/>
+<use x='171.531' xlink:href='#g2-104' y='158.367'/>
+<use x='175.904' xlink:href='#g2-56' y='158.367'/>
+<use x='180.138' xlink:href='#g2-98' y='158.367'/>
+<use x='184.746' xlink:href='#g2-101' y='158.367'/>
+<use x='188.509' xlink:href='#g2-110' y='158.367'/>
+<use x='192.882' xlink:href='#g2-99' y='158.367'/>
+<use x='196.646' xlink:href='#g2-104' y='158.367'/>
+<use x='201.018' xlink:href='#g2-78' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 59.571)'>
+<use x='168.285' xlink:href='#g2-120' y='158.367'/>
+<use x='172.187' xlink:href='#g2-109' y='158.367'/>
+<use x='178.912' xlink:href='#g2-97' y='158.367'/>
+<use x='182.98' xlink:href='#g2-108' y='158.367'/>
+<use x='185' xlink:href='#g2-108' y='158.367'/>
+<use x='187.02' xlink:href='#g2-111' y='158.367'/>
+<use x='191.49' xlink:href='#g2-99' y='158.367'/>
+<use x='195.254' xlink:href='#g2-45' y='158.367'/>
+<use x='198.076' xlink:href='#g2-116' y='158.367'/>
+<use x='201.134' xlink:href='#g2-101' y='158.367'/>
+<use x='204.898' xlink:href='#g2-115' y='158.367'/>
+<use x='208.144' xlink:href='#g2-116' y='158.367'/>
+<use x='211.202' xlink:href='#g2-78' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 59.571)'>
+<use x='168.285' xlink:href='#g2-99' y='158.367'/>
+<use x='172.049' xlink:href='#g2-97' y='158.367'/>
+<use x='176.117' xlink:href='#g2-99' y='158.367'/>
+<use x='179.88' xlink:href='#g2-104' y='158.367'/>
+<use x='184.253' xlink:href='#g2-101' y='158.367'/>
+<use x='188.017' xlink:href='#g2-45' y='158.367'/>
+<use x='190.839' xlink:href='#g2-115' y='158.367'/>
+<use x='194.086' xlink:href='#g2-99' y='158.367'/>
+<use x='197.849' xlink:href='#g2-114' y='158.367'/>
+<use x='200.741' xlink:href='#g2-97' y='158.367'/>
+<use x='204.81' xlink:href='#g2-116' y='158.367'/>
+<use x='207.868' xlink:href='#g2-99' y='158.367'/>
+<use x='211.631' xlink:href='#g2-104' y='158.367'/>
+<use x='216.004' xlink:href='#g2-78' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 47.205)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-120' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.894)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-120' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -15.418)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-120' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -46.729)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-120' y='158.367'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.041)'>
+<use x='168.285' xlink:href='#g1-50' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-120' y='158.367'/>
+</g>
+<path clip-path='url(#clip8)' d='M135.949 141.317H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M145.356 203.938H148.594V141.317H145.356ZM204.028 203.938H207.266V141.317H204.028ZM262.695 203.938H265.934V141.317H262.695ZM321.363 203.938H324.602V141.317H321.363ZM380.031 203.938H383.27V141.317H380.031ZM438.703 203.938H441.942V141.317H438.703Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M145.356 203.938H148.594V141.317H145.356ZM204.028 203.938H207.266V141.317H204.028ZM262.695 203.938H265.934V141.317H262.695ZM321.363 203.938H324.602V141.317H321.363ZM380.031 203.938H383.27V141.317H380.031ZM438.703 203.938H441.942V141.317H438.703Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M146.977 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M144.984 141.317H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M146.977 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M144.984 141.317H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M205.645 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M203.652 141.317H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M205.645 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M203.652 141.317H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M264.313 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M262.32 141.317H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M264.313 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M262.32 141.317H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M322.984 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M320.992 141.317H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M322.984 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M320.992 141.317H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M381.652 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M379.66 141.317H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M381.652 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M379.66 141.317H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M440.32 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M438.328 141.317H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M440.32 141.317V141.317' fill='#f0e0f0'/>
+<path clip-path='url(#clip8)' d='M438.328 141.317H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M150.586 203.938H153.824V137.809H150.586ZM209.258 203.938H212.496V144.196H209.258ZM267.926 203.938H271.164V140.563H267.926ZM326.594 203.938H329.832V141.754H326.594ZM385.262 203.938H388.5V188.406H385.262ZM443.934 203.938H447.172V110.754H443.934Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M150.586 203.938H153.824V137.809H150.586ZM209.258 203.938H212.496V144.196H209.258ZM267.926 203.938H271.164V140.563H267.926ZM326.594 203.938H329.832V141.754H326.594ZM385.262 203.938H388.5V188.406H385.262ZM443.934 203.938H447.172V110.754H443.934Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M152.207 137.809V137.809' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M150.215 137.809H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M152.207 137.809V137.809' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M150.215 137.809H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M210.875 144.196V144.196' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M208.883 144.195H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M210.875 144.196V144.196' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M208.883 144.195H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M269.543 140.563V140.563' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M267.551 140.562H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M269.543 140.563V140.563' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M267.551 140.562H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M328.215 141.754V141.754' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M326.223 141.754H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M328.215 141.754V141.754' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M326.223 141.754H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M386.883 188.406V188.406' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M384.891 188.406H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M386.883 188.406V188.406' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M384.891 188.406H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M445.551 110.754V110.754' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M443.559 110.754H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M445.551 110.754V110.754' fill='#e1c2e1'/>
+<path clip-path='url(#clip8)' d='M443.559 110.754H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M155.817 203.938H159.055V140.313H155.817ZM214.488 203.938H217.727V147.453H214.488ZM273.156 203.938H276.395V139.625H273.156ZM331.824 203.938H335.063V130.043H331.824ZM390.492 203.938H393.731V170.809H390.492ZM449.164 203.938H452.402V120.024H449.164Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M155.817 203.938H159.055V140.313H155.817ZM214.488 203.938H217.727V147.453H214.488ZM273.156 203.938H276.395V139.625H273.156ZM331.824 203.938H335.063V130.043H331.824ZM390.492 203.938H393.731V170.809H390.492ZM449.164 203.938H452.402V120.024H449.164Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M157.438 140.313V140.313' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M155.445 140.313H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M157.438 140.313V140.313' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M155.445 140.313H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M216.106 147.453V147.453' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M214.113 147.453H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M216.106 147.453V147.453' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M214.113 147.453H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M274.774 139.625V139.625' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M272.781 139.625H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M274.774 139.625V139.625' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M272.781 139.625H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M333.445 130.043V130.043' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M331.453 130.043H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M333.445 130.043V130.043' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M331.453 130.043H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M392.113 170.809V170.809' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M390.121 170.808H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M392.113 170.809V170.809' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M390.121 170.808H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M450.781 120.024V120.024' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M448.789 120.023H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M450.781 120.024V120.024' fill='#d1a3d1'/>
+<path clip-path='url(#clip8)' d='M448.789 120.023H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M161.047 203.938H164.285V137.559H161.047ZM219.719 203.938H222.957V144.383H219.719ZM278.387 203.938H281.625V131.36H278.387ZM337.055 203.938H340.293V128.164H337.055ZM395.723 203.938H398.961V138.121H395.723ZM454.395 203.938H457.633V137.559H454.395Z' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M161.047 203.938H164.285V137.559H161.047ZM219.719 203.938H222.957V144.383H219.719ZM278.387 203.938H281.625V131.36H278.387ZM337.055 203.938H340.293V128.164H337.055ZM395.723 203.938H398.961V138.121H395.723ZM454.395 203.938H457.633V137.559H454.395Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M162.668 137.559V137.559' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M160.676 137.558H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M162.668 137.559V137.559' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M160.676 137.558H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M221.336 144.383V144.383' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M219.344 144.382H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M221.336 144.383V144.383' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M219.344 144.382H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M280.004 131.36V131.36' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M278.012 131.36H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M280.004 131.36V131.36' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M278.012 131.36H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M338.676 128.164V128.164' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M336.684 128.164H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M338.676 128.164V128.164' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M336.684 128.164H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M397.344 138.121V138.121' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M395.352 138.121H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M397.344 138.121V138.121' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M395.352 138.121H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M456.012 137.559V137.559' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M454.02 137.558H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M456.012 137.559V137.559' fill='#c285c2'/>
+<path clip-path='url(#clip8)' d='M454.02 137.558H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M166.278 203.938H169.516V126.723H166.278ZM224.949 203.938H228.188V141.629H224.949ZM283.617 203.938H286.856V104.055H283.617ZM342.285 203.938H345.524V122.84H342.285ZM400.953 203.938H404.192V186.215H400.953ZM459.625 203.938H462.863V140.188H459.625Z' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M166.278 203.938H169.516V126.723H166.278ZM224.949 203.938H228.188V141.629H224.949ZM283.617 203.938H286.856V104.055H283.617ZM342.285 203.938H345.524V122.84H342.285ZM400.953 203.938H404.192V186.215H400.953ZM459.625 203.938H462.863V140.188H459.625Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M167.899 126.723V126.723' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M165.906 126.723H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M167.899 126.723V126.723' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M165.906 126.723H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M226.567 141.629V141.629' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M224.574 141.629H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M226.567 141.629V141.629' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M224.574 141.629H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M285.234 104.055V104.055' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M283.242 104.055H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M285.234 104.055V104.055' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M283.242 104.055H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M343.906 122.84V122.84' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M341.914 122.84H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M343.906 122.84V122.84' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M341.914 122.84H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M402.574 186.215V186.215' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M400.582 186.215H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M402.574 186.215V186.215' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M400.582 186.215H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M461.242 140.188V140.188' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M459.25 140.188H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M461.242 140.188V140.188' fill='#b366b3'/>
+<path clip-path='url(#clip8)' d='M459.25 140.188H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M171.508 203.938H174.746V115.828H171.508ZM230.18 203.938H233.414V91.215H230.18ZM288.848 203.938H292.086V95.977H288.848ZM347.516 203.938H350.754V78.692H347.516ZM406.184 203.938H409.422V167.68H406.184ZM464.856 203.938H468.094V130.856H464.856Z' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M171.508 203.938H174.746V115.828H171.508ZM230.18 203.938H233.414V91.215H230.18ZM288.848 203.938H292.086V95.977H288.848ZM347.516 203.938H350.754V78.692H347.516ZM406.184 203.938H409.422V167.68H406.184ZM464.856 203.938H468.094V130.856H464.856Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M173.129 115.828V115.828' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M171.137 115.828H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M173.129 115.828V115.828' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M171.137 115.828H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M231.797 91.215V91.215' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M229.805 91.215H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M231.797 91.215V91.215' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M229.805 91.215H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M290.465 95.977V95.977' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M288.473 95.977H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M290.465 95.977V95.977' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M288.473 95.977H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M349.137 78.692V78.692' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M347.145 78.691H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M349.137 78.692V78.692' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M347.145 78.691H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M407.805 167.68V167.68' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M405.813 167.68H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M407.805 167.68V167.68' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M405.813 167.68H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M466.473 130.856V130.856' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M464.481 130.856H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M466.473 130.856V130.856' fill='#a447a4'/>
+<path clip-path='url(#clip8)' d='M464.481 130.856H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M176.738 203.938H179.977V126.973H176.738ZM235.41 203.938H238.645V141.754H235.41ZM294.078 203.938H297.317V104.18H294.078ZM352.746 203.938H355.984V122.903H352.746ZM411.414 203.938H414.652V186.278H411.414ZM470.086 203.938H473.324V140.688H470.086Z' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M176.738 203.938H179.977V126.973H176.738ZM235.41 203.938H238.645V141.754H235.41ZM294.078 203.938H297.317V104.18H294.078ZM352.746 203.938H355.984V122.903H352.746ZM411.414 203.938H414.652V186.278H411.414ZM470.086 203.938H473.324V140.688H470.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M178.36 126.973V126.973' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M176.367 126.972H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M178.36 126.973V126.973' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M176.367 126.972H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M237.027 141.754V141.754' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M235.035 141.754H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M237.027 141.754V141.754' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M235.035 141.754H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M295.695 104.18V104.18' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M293.703 104.179H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M295.695 104.18V104.18' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M293.703 104.179H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M354.367 122.903V122.903' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M352.375 122.903H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M354.367 122.903V122.903' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M352.375 122.903H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M413.035 186.278V186.278' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M411.043 186.277H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M413.035 186.278V186.278' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M411.043 186.277H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M471.703 140.688V140.688' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M469.711 140.688H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M471.703 140.688V140.688' fill='#942994'/>
+<path clip-path='url(#clip8)' d='M469.711 140.688H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M416.645 203.938H419.883V157.973H416.645ZM181.969 203.938H185.207V135.051H181.969ZM240.641 203.938H243.875V142.129H240.641ZM299.309 203.938H302.547V134.676H299.309ZM357.977 203.938H361.215V140.25H357.977ZM475.317 203.938H478.555V131.235H475.317Z' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M416.645 203.938H419.883V157.973H416.645ZM181.969 203.938H185.207V135.051H181.969ZM240.641 203.938H243.875V142.129H240.641ZM299.309 203.938H302.547V134.676H299.309ZM357.977 203.938H361.215V140.25H357.977ZM475.317 203.938H478.555V131.235H475.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M418.266 157.973V157.973' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M416.274 157.973H420.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M418.266 157.973V157.973' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M416.274 157.973H420.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M183.59 135.051V135.051' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M181.598 135.051H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M183.59 135.051V135.051' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M181.598 135.051H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M242.258 142.129V142.129' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M240.266 142.129H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M242.258 142.129V142.129' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M240.266 142.129H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M300.926 134.676V134.676' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M298.933 134.676H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M300.926 134.676V134.676' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M298.933 134.676H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M359.598 140.25V140.25' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M357.606 140.25H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M359.598 140.25V140.25' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M357.606 140.25H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M476.934 131.235V131.235' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M474.942 131.235H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M476.934 131.235V131.235' fill='#850a85'/>
+<path clip-path='url(#clip8)' d='M474.942 131.235H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip8)' d='M418.387 251.164H487.762V229.188H418.387Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 253.422 88.837)'>
+<use x='168.285' xlink:href='#g1-114' y='147.13'/>
+<use x='170.092' xlink:href='#g1-53' y='147.13'/>
+<use x='172.739' xlink:href='#g1-97' y='147.13'/>
+<use x='175.281' xlink:href='#g1-45' y='147.13'/>
+<use x='177.046' xlink:href='#g1-52' y='147.13'/>
+<use x='179.692' xlink:href='#g1-120' y='147.13'/>
+<use x='182.131' xlink:href='#g1-108' y='147.13'/>
+<use x='183.393' xlink:href='#g1-97' y='147.13'/>
+<use x='185.789' xlink:href='#g1-114' y='147.13'/>
+<use x='187.596' xlink:href='#g1-103' y='147.13'/>
+<use x='190.243' xlink:href='#g1-101' y='147.13'/>
+<use x='192.595' xlink:href='#g1-44' y='147.13'/>
+<use x='195.83' xlink:href='#g1-49' y='147.13'/>
+<use x='198.476' xlink:href='#g1-50' y='147.13'/>
+<use x='201.122' xlink:href='#g1-56' y='147.13'/>
+<use x='203.769' xlink:href='#g1-71' y='147.13'/>
+<use x='207.297' xlink:href='#g1-98' y='147.13'/>
+<use x='168.285' xlink:href='#g1-49' y='152.749'/>
+<use x='170.931' xlink:href='#g1-54' y='152.749'/>
+<use x='173.578' xlink:href='#g1-45' y='152.749'/>
+<use x='175.342' xlink:href='#g1-99' y='152.749'/>
+<use x='177.694' xlink:href='#g1-111' y='152.749'/>
+<use x='180.193' xlink:href='#g1-114' y='152.749'/>
+<use x='182.001' xlink:href='#g1-101' y='152.749'/>
+<use x='186.118' xlink:href='#g1-65' y='152.749'/>
+<use x='189.646' xlink:href='#g1-77' y='152.749'/>
+<use x='194.264' xlink:href='#g1-68' y='152.749'/>
+<use x='199.851' xlink:href='#g1-69' y='152.749'/>
+<use x='203.025' xlink:href='#g1-112' y='152.749'/>
+<use x='205.611' xlink:href='#g1-121' y='152.749'/>
+<use x='208.049' xlink:href='#g1-99' y='152.749'/>
+<use x='212.166' xlink:href='#g1-64' y='152.749'/>
+<use x='215.695' xlink:href='#g1-50' y='152.749'/>
+<use x='218.341' xlink:href='#g1-46' y='152.749'/>
+<use x='219.811' xlink:href='#g1-53' y='152.749'/>
+<use x='222.457' xlink:href='#g1-71' y='152.749'/>
+<use x='225.986' xlink:href='#g1-104' y='152.749'/>
+<use x='228.719' xlink:href='#g1-122' y='152.749'/>
+<use x='168.285' xlink:href='#g1-85' y='158.367'/>
+<use x='171.917' xlink:href='#g1-98' y='158.367'/>
+<use x='174.65' xlink:href='#g1-117' y='158.367'/>
+<use x='177.383' xlink:href='#g1-110' y='158.367'/>
+<use x='180.116' xlink:href='#g1-116' y='158.367'/>
+<use x='182.027' xlink:href='#g1-117' y='158.367'/>
+<use x='186.524' xlink:href='#g1-49' y='158.367'/>
+<use x='189.17' xlink:href='#g1-56' y='158.367'/>
+<use x='191.817' xlink:href='#g1-46' y='158.367'/>
+<use x='193.287' xlink:href='#g1-48' y='158.367'/>
+<use x='195.933' xlink:href='#g1-52' y='158.367'/>
+<use x='198.58' xlink:href='#g1-46' y='158.367'/>
+<use x='200.05' xlink:href='#g1-49' y='158.367'/>
+<use x='202.696' xlink:href='#g1-44' y='158.367'/>
+<use x='205.931' xlink:href='#g1-71' y='158.367'/>
+<use x='209.459' xlink:href='#g1-67' y='158.367'/>
+<use x='212.841' xlink:href='#g1-67' y='158.367'/>
+<use x='217.986' xlink:href='#g1-55' y='158.367'/>
+<use x='220.633' xlink:href='#g1-46' y='158.367'/>
+<use x='222.103' xlink:href='#g1-51' y='158.367'/>
+<use x='224.749' xlink:href='#g1-46' y='158.367'/>
+<use x='226.219' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.757 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 48.912 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 107.581 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.25 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 224.919 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 283.588 303.575)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 -4.526 300.068)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-54' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.143 306.456)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-53' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 112.812 302.824)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-49' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 171.481 304.013)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.15 350.668)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-53' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 288.819 273.015)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-52' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.704 302.573)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-50' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.373 309.712)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.042 301.884)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-51' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.711 292.303)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-56' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.38 333.071)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-51' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 294.049 282.283)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-51' y='158.367'/>
+<use x='175.048' xlink:href='#g1-52' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 5.935 299.818)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-54' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.604 306.644)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-53' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.273 293.618)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-54' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 181.942 290.424)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-49' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.611 300.381)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-53' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 299.28 299.818)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-54' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 11.165 288.984)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-51' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 69.834 303.888)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.503 266.314)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 187.172 285.101)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 245.841 348.476)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-56' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 304.51 302.448)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-50' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 16.396 278.088)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-52' y='158.367'/>
+<use x='175.048' xlink:href='#g1-49' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 75.065 253.477)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-56' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.734 258.236)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-55' y='158.367'/>
+<use x='175.048' xlink:href='#g1-50' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 192.403 240.952)'>
+<use x='163.396' xlink:href='#g3-1' y='158.367'/>
+<use x='166.901' xlink:href='#g3-1' y='158.367'/>
+<use x='170.407' xlink:href='#g3-1' y='158.367'/>
+<use x='173.912' xlink:href='#g1-50' y='158.367'/>
+<use x='176.558' xlink:href='#g1-46' y='158.367'/>
+<use x='178.029' xlink:href='#g1-52' y='158.367'/>
+<use x='180.675' xlink:href='#g1-54' y='158.367'/>
+<use x='183.321' xlink:href='#g1-120' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 251.072 329.939)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-56' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 309.741 293.117)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-55' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.626 289.234)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-51' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 80.295 304.013)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.964 266.44)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-53' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.633 285.164)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 256.302 348.538)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-50' y='158.367'/>
+<use x='175.048' xlink:href='#g1-56' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 314.971 302.949)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-49' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.532 320.233)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-55' y='158.367'/>
+<use x='175.048' xlink:href='#g1-51' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.856 297.313)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-48' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.525 304.389)'>
+<use x='168.285' xlink:href='#g1-48' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-57' y='158.367'/>
+<use x='175.048' xlink:href='#g1-57' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 144.194 296.937)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-49' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.863 302.511)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-48' y='158.367'/>
+<use x='175.048' xlink:href='#g1-50' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 320.201 293.493)'>
+<use x='168.285' xlink:href='#g1-49' y='158.367'/>
+<use x='170.931' xlink:href='#g1-46' y='158.367'/>
+<use x='172.401' xlink:href='#g1-49' y='158.367'/>
+<use x='175.048' xlink:href='#g1-54' y='158.367'/>
+</g>
+<g transform='matrix(0 -1 1 0 -45.209 361.494)'>
+<use x='168.285' xlink:href='#g0-82' y='158.367'/>
+<use x='174.255' xlink:href='#g0-101' y='158.367'/>
+<use x='178.351' xlink:href='#g0-108' y='158.367'/>
+<use x='180.551' xlink:href='#g0-97' y='158.367'/>
+<use x='184.979' xlink:href='#g0-116' y='158.367'/>
+<use x='188.307' xlink:href='#g0-105' y='158.367'/>
+<use x='190.507' xlink:href='#g0-118' y='158.367'/>
+<use x='194.755' xlink:href='#g0-101' y='158.367'/>
+<use x='201.922' xlink:href='#g0-114' y='158.367'/>
+<use x='205.07' xlink:href='#g0-115' y='158.367'/>
+<use x='208.603' xlink:href='#g0-115' y='158.367'/>
+<use x='215.207' xlink:href='#g2-40' y='158.367'/>
+<use x='218.5' xlink:href='#g2-108' y='158.367'/>
+<use x='220.521' xlink:href='#g2-111' y='158.367'/>
+<use x='224.52' xlink:href='#g2-119' y='158.367'/>
+<use x='230.068' xlink:href='#g2-101' y='158.367'/>
+<use x='233.832' xlink:href='#g2-114' y='158.367'/>
+<use x='239.547' xlink:href='#g2-105' y='158.367'/>
+<use x='241.567' xlink:href='#g2-115' y='158.367'/>
+<use x='247.636' xlink:href='#g2-98' y='158.367'/>
+<use x='252.244' xlink:href='#g2-101' y='158.367'/>
+<use x='256.008' xlink:href='#g2-116' y='158.367'/>
+<use x='259.066' xlink:href='#g2-116' y='158.367'/>
+<use x='262.124' xlink:href='#g2-101' y='158.367'/>
+<use x='265.887' xlink:href='#g2-114' y='158.367'/>
+<use x='268.779' xlink:href='#g2-41' y='158.367'/>
+</g>
+<path d='M136.149 249.309H349.488V232.317H136.149Z' fill='#ffffff'/>
+<path d='M136.149 249.309H349.488V232.317H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 242.804H142.324V234.835H139.336ZM145.313 242.804H148.301V236.828H145.313Z' fill='#f0e0f0'/>
+<path d='M139.336 242.804H142.324V234.835H139.336ZM145.313 242.804H148.301V236.828H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 84.43)'>
+<use x='185.011' xlink:href='#g2-109' y='158.367'/>
+<use x='191.736' xlink:href='#g2-105' y='158.367'/>
+</g>
+<path d='M163.422 242.805H166.41V234.836H163.422ZM169.398 242.805H172.391V236.828H169.398Z' fill='#e1c2e1'/>
+<path d='M163.422 242.804H166.41V234.835H163.422ZM169.398 242.804H172.391V236.828H169.398Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 83.976)'>
+<use x='208.137' xlink:href='#g2-116' y='158.367'/>
+<use x='211.195' xlink:href='#g2-99' y='158.367'/>
+</g>
+<path d='M185.586 242.805H188.574V234.836H185.586ZM191.563 242.805H194.555V236.828H191.563Z' fill='#d1a3d1'/>
+<path d='M185.586 242.804H188.574V234.835H185.586ZM191.563 242.804H194.555V236.828H191.563Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 84.43)'>
+<use x='229.9' xlink:href='#g2-106' y='158.367'/>
+<use x='232.155' xlink:href='#g2-101' y='158.367'/>
+</g>
+<path d='M206.949 242.805H209.938V234.836H206.949ZM212.926 242.805H215.914V236.828H212.926Z' fill='#c285c2'/>
+<path d='M206.949 242.804H209.938V234.835H206.949ZM212.926 242.804H215.914V236.828H212.926Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 83.47)'>
+<use x='252.061' xlink:href='#g2-115' y='158.367'/>
+<use x='255.307' xlink:href='#g2-110' y='158.367'/>
+</g>
+<path d='M229.91 242.805H232.898V234.836H229.91ZM235.887 242.805H238.875V236.828H235.887Z' fill='#b366b3'/>
+<path d='M229.91 242.804H232.898V234.835H229.91ZM235.887 242.804H238.875V236.828H235.887Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 83.47)'>
+<use x='274.845' xlink:href='#g2-114' y='158.367'/>
+<use x='277.737' xlink:href='#g2-112' y='158.367'/>
+</g>
+<path d='M252.516 242.805H255.504V234.836H252.516ZM258.496 242.805H261.484V236.828H258.496Z' fill='#a447a4'/>
+<path d='M252.516 242.804H255.504V234.835H252.516ZM258.496 242.804H261.484V236.828H258.496Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 84.467)'>
+<use x='303.672' xlink:href='#g2-104' y='158.367'/>
+<use x='308.045' xlink:href='#g2-111' y='158.367'/>
+<use x='312.279' xlink:href='#g2-97' y='158.367'/>
+<use x='316.112' xlink:href='#g2-114' y='158.367'/>
+<use x='319.004' xlink:href='#g2-100' y='158.367'/>
+</g>
+<path d='M287.563 242.805H290.551V234.836H287.563ZM293.543 242.805H296.531V236.828H293.543Z' fill='#942994'/>
+<path d='M287.563 242.804H290.551V234.835H287.563ZM293.543 242.804H296.531V236.828H293.543Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 84.467)'>
+<use x='337.19' xlink:href='#g2-103' y='158.367'/>
+<use x='341.424' xlink:href='#g2-108' y='158.367'/>
+<use x='343.444' xlink:href='#g2-105' y='158.367'/>
+<use x='345.464' xlink:href='#g2-98' y='158.367'/>
+<use x='350.072' xlink:href='#g2-99' y='158.367'/>
+</g>
+<path d='M319.551 242.805H322.539V234.836H319.551ZM325.527 242.805H328.52V236.828H325.527Z' fill='#850a85'/>
+<path d='M319.551 242.804H322.539V234.835H319.551ZM325.527 242.804H328.52V236.828H325.527Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 84.467)'>
+<use x='366.757' xlink:href='#g2-116' y='158.367'/>
+<use x='369.815' xlink:href='#g2-98' y='158.367'/>
+<use x='374.187' xlink:href='#g2-98' y='158.367'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-spec-rss.svg b/extlib/mimalloc/doc/bench-2020/bench-spec-rss.svg
new file mode 100644 (file)
index 0000000..2c93616
--- /dev/null
@@ -0,0 +1,713 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='182.025pt' version='1.1' viewBox='106.736 51.674 270.486 182.025' width='270.486pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip6'>
+<path d='M135.949 186.074H355.586V60.828H135.949Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-46' transform='scale(1.6)' xlink:href='#g1-46'/>
+<use id='g2-48' transform='scale(1.6)' xlink:href='#g1-48'/>
+<use id='g2-50' transform='scale(1.6)' xlink:href='#g1-50'/>
+<use id='g2-51' transform='scale(1.6)' xlink:href='#g1-51'/>
+<use id='g2-52' transform='scale(1.6)' xlink:href='#g1-52'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-107' transform='scale(1.6)' xlink:href='#g1-107'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M3.248 -3.457H2.745V-1.963H0.986V-3.457H0.483V0H0.986V-1.634H2.745V0H3.248V-3.457Z' id='g1-72'/>
+<path d='M0.986 -3.457H0.483V0H0.986V-3.457Z' id='g1-73'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.611 -1.714C3.611 -2.745 2.854 -3.562 1.953 -3.562S0.294 -2.745 0.294 -1.714S1.061 0.105 1.953 0.105C2.849 0.105 3.611 -0.687 3.611 -1.714ZM1.953 -0.249C1.35 -0.249 0.797 -0.852 0.797 -1.793C0.797 -2.675 1.355 -3.218 1.953 -3.218S3.108 -2.675 3.108 -1.793C3.108 -0.847 2.555 -0.249 1.953 -0.249Z' id='g1-79'/>
+<path d='M1.868 -1.42C2.511 -1.42 3.083 -1.873 3.083 -2.446C3.083 -2.979 2.555 -3.457 1.833 -3.457H0.488V0H0.991V-1.42H1.868ZM1.709 -3.163C2.271 -3.163 2.63 -2.864 2.63 -2.446C2.63 -2.037 2.291 -1.729 1.709 -1.729H0.976V-3.163H1.709Z' id='g1-80'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M1.968 -1.823L3.228 -3.457H2.685L1.724 -2.182L0.742 -3.457H0.149L1.479 -1.823L0.075 0H0.618L1.724 -1.499L2.854 0H3.447L1.968 -1.823Z' id='g1-88'/>
+<path d='M2.934 -3.238V-3.457H0.369V-3.123H1.41C1.479 -3.123 1.539 -3.128 1.609 -3.128H2.291L0.294 -0.229V0H2.964V-0.354H2.466C1.958 -0.354 1.45 -0.344 0.941 -0.344L2.934 -3.238Z' id='g1-90'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M1.489 -1.355L2.376 -2.212H1.893L0.827 -1.181V-3.457H0.438V0H0.807V-0.697L1.23 -1.106L2.052 0H2.491L1.489 -1.355Z' id='g1-107'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g0-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g0-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page6'>
+<path d='M190.86 194.93V186.074M245.766 194.93V186.074M300.676 194.93V186.074M190.86 51.973V60.828M245.766 51.973V60.828M300.676 51.973V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M163.403 190.324V186.074M218.313 190.324V186.074M273.223 190.324V186.074M328.133 190.324V186.074M163.403 56.574V60.828M218.313 56.574V60.828M273.223 56.574V60.828M328.133 56.574V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 186.074H140.199M135.949 154.762H140.199M135.949 123.449H140.199M135.949 92.141H140.199M135.949 60.828H140.199M355.586 186.074H351.336M355.586 154.762H351.336M355.586 123.449H351.336M355.586 92.141H351.336M355.586 60.828H351.336' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 186.074V60.828H355.586V186.074H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -18.291 59.571)'>
+<use x='168.285' xlink:href='#g2-54' y='140.503'/>
+<use x='172.519' xlink:href='#g2-48' y='140.503'/>
+<use x='176.753' xlink:href='#g2-50' y='140.503'/>
+<use x='180.987' xlink:href='#g2-46' y='140.503'/>
+<use x='183.34' xlink:href='#g2-103' y='140.503'/>
+<use x='187.574' xlink:href='#g2-99' y='140.503'/>
+<use x='191.338' xlink:href='#g2-99' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 27.05 59.571)'>
+<use x='168.285' xlink:href='#g2-54' y='140.503'/>
+<use x='172.519' xlink:href='#g2-50' y='140.503'/>
+<use x='176.753' xlink:href='#g2-48' y='140.503'/>
+<use x='180.987' xlink:href='#g2-46' y='140.503'/>
+<use x='183.34' xlink:href='#g2-111' y='140.503'/>
+<use x='187.574' xlink:href='#g2-109' y='140.503'/>
+<use x='194.299' xlink:href='#g2-110' y='140.503'/>
+<use x='198.671' xlink:href='#g2-101' y='140.503'/>
+<use x='202.435' xlink:href='#g2-116' y='140.503'/>
+<use x='205.493' xlink:href='#g2-112' y='140.503'/>
+<use x='209.866' xlink:href='#g2-112' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 78.694 59.571)'>
+<use x='168.285' xlink:href='#g2-54' y='140.503'/>
+<use x='172.519' xlink:href='#g2-50' y='140.503'/>
+<use x='176.753' xlink:href='#g2-51' y='140.503'/>
+<use x='180.987' xlink:href='#g2-46' y='140.503'/>
+<use x='183.34' xlink:href='#g2-120' y='140.503'/>
+<use x='187.242' xlink:href='#g2-97' y='140.503'/>
+<use x='191.31' xlink:href='#g2-108' y='140.503'/>
+<use x='193.33' xlink:href='#g2-97' y='140.503'/>
+<use x='197.398' xlink:href='#g2-110' y='140.503'/>
+<use x='201.771' xlink:href='#g2-99' y='140.503'/>
+<use x='205.535' xlink:href='#g2-98' y='140.503'/>
+<use x='209.907' xlink:href='#g2-109' y='140.503'/>
+<use x='216.632' xlink:href='#g2-107' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 134.081 59.571)'>
+<use x='168.285' xlink:href='#g2-54' y='140.503'/>
+<use x='172.519' xlink:href='#g2-52' y='140.503'/>
+<use x='176.753' xlink:href='#g2-56' y='140.503'/>
+<use x='180.987' xlink:href='#g2-46' y='140.503'/>
+<use x='183.34' xlink:href='#g2-101' y='140.503'/>
+<use x='187.103' xlink:href='#g2-120' y='140.503'/>
+<use x='191.006' xlink:href='#g2-99' y='140.503'/>
+<use x='194.769' xlink:href='#g2-104' y='140.503'/>
+<use x='199.142' xlink:href='#g2-97' y='140.503'/>
+<use x='203.21' xlink:href='#g2-110' y='140.503'/>
+<use x='207.582' xlink:href='#g2-103' y='140.503'/>
+<use x='211.817' xlink:href='#g2-101' y='140.503'/>
+<use x='215.58' xlink:href='#g2-50' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 47.205)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.894)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -15.418)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -46.729)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.041)'>
+<use x='168.285' xlink:href='#g1-50' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<path clip-path='url(#clip6)' d='M135.949 123.449H355.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M140.863 186.074H144.102V123.449H140.863ZM195.77 186.074H199.008V123.449H195.77ZM250.68 186.074H253.918V123.449H250.68ZM305.59 186.074H308.828V123.449H305.59Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M140.863 186.074H144.102V123.449H140.863ZM195.77 186.074H199.008V123.449H195.77ZM250.68 186.074H253.918V123.449H250.68ZM305.59 186.074H308.828V123.449H305.59Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M142.481 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M140.488 123.449H144.472' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M142.481 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M140.488 123.449H144.472' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M197.391 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M195.398 123.449H199.383' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M197.391 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M195.398 123.449H199.383' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M252.301 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M250.308 123.449H254.292' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M252.301 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M250.308 123.449H254.292' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M307.211 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M305.219 123.449H309.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M307.211 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip6)' d='M305.219 123.449H309.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M146.094 186.074H149.332V123.262H146.094ZM201 186.074H204.238V123.137H201ZM255.91 186.074H259.149V124.141H255.91ZM310.82 186.074H314.059V73.664H310.82Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M146.094 186.074H149.332V123.262H146.094ZM201 186.074H204.238V123.137H201ZM255.91 186.074H259.149V124.141H255.91ZM310.82 186.074H314.059V73.664H310.82Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M147.711 123.262V123.262' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M145.719 123.262H149.703' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M147.711 123.262V123.262' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M145.719 123.262H149.703' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M202.621 123.137V123.137' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M200.629 123.137H204.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M202.621 123.137V123.137' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M200.629 123.137H204.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M257.531 124.141V124.141' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M255.539 124.141H259.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M257.531 124.141V124.141' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M255.539 124.141H259.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M312.442 73.664V73.664' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M310.449 73.664H314.433' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M312.442 73.664V73.664' fill='#e1c2e1'/>
+<path clip-path='url(#clip6)' d='M310.449 73.664H314.433' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M151.324 186.074H154.563V121.762H151.324ZM206.231 186.074H209.469V123.891H206.231ZM261.141 186.074H264.379V121.321H261.141ZM316.051 186.074H319.289V94.52H316.051Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M151.324 186.074H154.563V121.762H151.324ZM206.231 186.074H209.469V123.891H206.231ZM261.141 186.074H264.379V121.321H261.141ZM316.051 186.074H319.289V94.52H316.051Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M152.942 121.762V121.762' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M150.949 121.762H154.933' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M152.942 121.762V121.762' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M150.949 121.762H154.933' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M207.852 123.891V123.891' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M205.86 123.89H209.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M207.852 123.891V123.891' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M205.86 123.89H209.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M262.762 121.321V121.321' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M260.769 121.321H264.753' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M262.762 121.321V121.321' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M260.769 121.321H264.753' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M317.672 94.52V94.52' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M315.68 94.52H319.664' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M317.672 94.52V94.52' fill='#d1a3d1'/>
+<path clip-path='url(#clip6)' d='M315.68 94.52H319.664' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M156.555 186.074H159.793V122.449H156.555ZM211.461 186.074H214.699V124.328H211.461ZM266.371 186.074H269.609V124.953H266.371ZM321.281 186.074H324.52V106.168H321.281Z' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M156.555 186.074H159.793V122.449H156.555ZM211.461 186.074H214.699V124.328H211.461ZM266.371 186.074H269.609V124.953H266.371ZM321.281 186.074H324.52V106.168H321.281Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M158.172 122.449V122.449' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M156.18 122.449H160.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M158.172 122.449V122.449' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M156.18 122.449H160.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M213.082 124.328V124.328' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M211.09 124.329H215.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M213.082 124.328V124.328' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M211.09 124.329H215.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M267.992 124.953V124.953' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M266 124.953H269.985' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M267.992 124.953V124.953' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M266 124.953H269.985' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M322.902 106.168V106.168' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M320.91 106.168H324.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M322.902 106.168V106.168' fill='#c285c2'/>
+<path clip-path='url(#clip6)' d='M320.91 106.168H324.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M161.785 186.074H165.024V123.891H161.785ZM216.692 186.074H219.93V122.262H216.692ZM271.602 186.074H274.84V127.395H271.602ZM326.512 186.074H329.75V125.328H326.512Z' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M161.785 186.074H165.024V123.891H161.785ZM216.692 186.074H219.93V122.262H216.692ZM271.602 186.074H274.84V127.395H271.602ZM326.512 186.074H329.75V125.328H326.512Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M163.403 123.891V123.891' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M161.41 123.89H165.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M163.403 123.891V123.891' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M161.41 123.89H165.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M218.313 122.262V122.262' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M216.321 122.262H220.305' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M218.313 122.262V122.262' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M216.321 122.262H220.305' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M273.223 127.395V127.395' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M271.23 127.394H275.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M273.223 127.395V127.395' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M271.23 127.394H275.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M328.133 125.328V125.328' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M326.141 125.329H330.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M328.133 125.328V125.328' fill='#b366b3'/>
+<path clip-path='url(#clip6)' d='M326.141 125.329H330.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M167.016 186.074H170.254V104.914H167.016ZM221.922 186.074H225.16V113.18H221.922ZM276.832 186.074H280.07V100.781H276.832ZM331.742 186.074H334.981V71.848H331.742Z' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M167.016 186.074H170.254V104.914H167.016ZM221.922 186.074H225.16V113.18H221.922ZM276.832 186.074H280.07V100.781H276.832ZM331.742 186.074H334.981V71.848H331.742Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M168.633 104.914V104.914' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M166.641 104.914H170.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M168.633 104.914V104.914' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M166.641 104.914H170.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M223.543 113.18V113.18' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M221.551 113.18H225.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M223.543 113.18V113.18' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M221.551 113.18H225.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M278.453 100.781V100.781' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M276.461 100.781H280.446' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M278.453 100.781V100.781' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M276.461 100.781H280.446' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M333.363 71.848V71.848' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M331.371 71.848H335.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M333.363 71.848V71.848' fill='#a447a4'/>
+<path clip-path='url(#clip6)' d='M331.371 71.848H335.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M172.246 186.074H175.485V123.891H172.246ZM227.153 186.074H230.391V122.324H227.153ZM282.063 186.074H285.301V127.395H282.063ZM336.973 186.074H340.211V123.891H336.973Z' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M172.246 186.074H175.485V123.891H172.246ZM227.153 186.074H230.391V122.324H227.153ZM282.063 186.074H285.301V127.395H282.063ZM336.973 186.074H340.211V123.891H336.973Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M173.863 123.891V123.891' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M171.871 123.89H175.855' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M173.863 123.891V123.891' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M171.871 123.89H175.855' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M228.774 122.324V122.324' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M226.782 122.325H230.766' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M228.774 122.324V122.324' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M226.782 122.325H230.766' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M283.684 127.395V127.395' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M281.691 127.394H285.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M283.684 127.395V127.395' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M281.691 127.394H285.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M338.594 123.891V123.891' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M336.602 123.89H340.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M338.594 123.891V123.891' fill='#942994'/>
+<path clip-path='url(#clip6)' d='M336.602 123.89H340.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M177.477 186.074H180.715V104.602H177.477ZM232.383 186.074H235.621V113.367H232.383ZM287.293 186.074H290.531V112.117H287.293ZM342.203 186.074H345.442V103.16H342.203Z' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M177.477 186.074H180.715V104.602H177.477ZM232.383 186.074H235.621V113.367H232.383ZM287.293 186.074H290.531V112.117H287.293ZM342.203 186.074H345.442V103.16H342.203Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M179.094 104.602V104.602' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M177.102 104.601H181.086' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M179.094 104.602V104.602' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M177.102 104.601H181.086' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M234.004 113.367V113.367' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M232.012 113.368H235.996' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M234.004 113.367V113.367' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M232.012 113.368H235.996' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M288.914 112.117V112.117' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M286.922 112.117H290.907' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M288.914 112.117V112.117' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M286.922 112.117H290.907' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M343.824 103.16V103.16' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M341.832 103.16H345.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M343.824 103.16V103.16' fill='#850a85'/>
+<path clip-path='url(#clip6)' d='M341.832 103.16H345.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M182.707 186.074H185.945V123.324H182.707ZM237.613 186.074H240.852V117.754H237.613ZM292.524 186.074H295.762V121.508H292.524ZM347.434 186.074H350.672V117.375H347.434Z' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M182.707 186.074H185.945V123.324H182.707ZM237.613 186.074H240.852V117.754H237.613ZM292.524 186.074H295.762V121.508H292.524ZM347.434 186.074H350.672V117.375H347.434Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M184.324 123.324V123.324' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M182.332 123.325H186.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M184.324 123.324V123.324' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M182.332 123.325H186.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M239.234 117.754V117.754' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M237.243 117.754H241.227' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M239.234 117.754V117.754' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M237.243 117.754H241.227' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M294.145 121.508V121.508' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M292.152 121.508H296.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M294.145 121.508V121.508' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M292.152 121.508H296.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M349.055 117.375V117.375' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M347.063 117.375H351.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M349.055 117.375V117.375' fill='#760076'/>
+<path clip-path='url(#clip6)' d='M347.063 117.375H351.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip6)' d='M287.102 233.301H355.387V211.324H287.102Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 122.136 88.837)'>
+<use x='168.285' xlink:href='#g1-72' y='129.265'/>
+<use x='172.021' xlink:href='#g1-80' y='129.265'/>
+<use x='175.402' xlink:href='#g1-45' y='129.265'/>
+<use x='177.167' xlink:href='#g1-90' y='129.265'/>
+<use x='180.401' xlink:href='#g1-52' y='129.265'/>
+<use x='183.047' xlink:href='#g1-45' y='129.265'/>
+<use x='184.812' xlink:href='#g1-71' y='129.265'/>
+<use x='188.34' xlink:href='#g1-52' y='129.265'/>
+<use x='190.987' xlink:href='#g1-44' y='129.265'/>
+<use x='194.221' xlink:href='#g1-49' y='129.265'/>
+<use x='196.867' xlink:href='#g1-54' y='129.265'/>
+<use x='199.514' xlink:href='#g1-71' y='129.265'/>
+<use x='203.042' xlink:href='#g1-98' y='129.265'/>
+<use x='168.285' xlink:href='#g1-56' y='134.884'/>
+<use x='170.931' xlink:href='#g1-45' y='134.884'/>
+<use x='172.695' xlink:href='#g1-99' y='134.884'/>
+<use x='175.048' xlink:href='#g1-111' y='134.884'/>
+<use x='177.547' xlink:href='#g1-114' y='134.884'/>
+<use x='179.355' xlink:href='#g1-101' y='134.884'/>
+<use x='183.471' xlink:href='#g1-73' y='134.884'/>
+<use x='184.941' xlink:href='#g1-110' y='134.884'/>
+<use x='187.674' xlink:href='#g1-116' y='134.884'/>
+<use x='189.585' xlink:href='#g1-101' y='134.884'/>
+<use x='191.938' xlink:href='#g1-108' y='134.884'/>
+<use x='194.965' xlink:href='#g1-88' y='134.884'/>
+<use x='198.493' xlink:href='#g1-69' y='134.884'/>
+<use x='201.667' xlink:href='#g1-79' y='134.884'/>
+<use x='205.576' xlink:href='#g1-78' y='134.884'/>
+<use x='211.076' xlink:href='#g1-64' y='134.884'/>
+<use x='214.605' xlink:href='#g1-50' y='134.884'/>
+<use x='217.251' xlink:href='#g1-46' y='134.884'/>
+<use x='218.721' xlink:href='#g1-55' y='134.884'/>
+<use x='221.368' xlink:href='#g1-71' y='134.884'/>
+<use x='224.896' xlink:href='#g1-104' y='134.884'/>
+<use x='227.629' xlink:href='#g1-122' y='134.884'/>
+<use x='168.285' xlink:href='#g1-85' y='140.503'/>
+<use x='171.917' xlink:href='#g1-98' y='140.503'/>
+<use x='174.65' xlink:href='#g1-117' y='140.503'/>
+<use x='177.383' xlink:href='#g1-110' y='140.503'/>
+<use x='180.116' xlink:href='#g1-116' y='140.503'/>
+<use x='182.027' xlink:href='#g1-117' y='140.503'/>
+<use x='186.524' xlink:href='#g1-49' y='140.503'/>
+<use x='189.17' xlink:href='#g1-56' y='140.503'/>
+<use x='191.817' xlink:href='#g1-46' y='140.503'/>
+<use x='193.287' xlink:href='#g1-48' y='140.503'/>
+<use x='195.933' xlink:href='#g1-52' y='140.503'/>
+<use x='198.58' xlink:href='#g1-46' y='140.503'/>
+<use x='200.05' xlink:href='#g1-49' y='140.503'/>
+<use x='202.696' xlink:href='#g1-44' y='140.503'/>
+<use x='205.931' xlink:href='#g1-71' y='140.503'/>
+<use x='209.459' xlink:href='#g1-67' y='140.503'/>
+<use x='212.841' xlink:href='#g1-67' y='140.503'/>
+<use x='217.986' xlink:href='#g1-55' y='140.503'/>
+<use x='220.633' xlink:href='#g1-46' y='140.503'/>
+<use x='222.103' xlink:href='#g1-52' y='140.503'/>
+<use x='224.749' xlink:href='#g1-46' y='140.503'/>
+<use x='226.219' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 3.612 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 58.522 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.431 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 168.341 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 8.843 285.523)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 63.752 285.398)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.662 286.4)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 173.571 235.926)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-55' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 14.073 284.02)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 68.983 286.149)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.892 283.582)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 178.802 256.779)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-52' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 19.304 284.709)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.213 286.588)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 129.123 287.214)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 184.032 268.427)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 24.534 286.149)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.444 284.521)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 134.353 289.656)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-52' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 189.263 287.59)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 29.765 267.175)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-51' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 84.674 275.441)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 139.584 263.042)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-51' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.493 234.11)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-56' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 34.995 286.149)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 89.905 284.584)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 144.814 289.656)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-52' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.724 286.149)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 40.226 266.862)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-51' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.135 275.629)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.045 274.376)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.954 265.421)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-51' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 45.456 285.586)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.366 280.012)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 155.275 283.77)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 210.185 279.637)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -27.345 343.63)'>
+<use x='168.285' xlink:href='#g0-82' y='140.503'/>
+<use x='174.255' xlink:href='#g0-101' y='140.503'/>
+<use x='178.351' xlink:href='#g0-108' y='140.503'/>
+<use x='180.551' xlink:href='#g0-97' y='140.503'/>
+<use x='184.979' xlink:href='#g0-116' y='140.503'/>
+<use x='188.307' xlink:href='#g0-105' y='140.503'/>
+<use x='190.507' xlink:href='#g0-118' y='140.503'/>
+<use x='194.755' xlink:href='#g0-101' y='140.503'/>
+<use x='201.922' xlink:href='#g0-114' y='140.503'/>
+<use x='205.07' xlink:href='#g0-115' y='140.503'/>
+<use x='208.603' xlink:href='#g0-115' y='140.503'/>
+<use x='215.207' xlink:href='#g2-40' y='140.503'/>
+<use x='218.5' xlink:href='#g2-108' y='140.503'/>
+<use x='220.521' xlink:href='#g2-111' y='140.503'/>
+<use x='224.52' xlink:href='#g2-119' y='140.503'/>
+<use x='230.068' xlink:href='#g2-101' y='140.503'/>
+<use x='233.832' xlink:href='#g2-114' y='140.503'/>
+<use x='239.547' xlink:href='#g2-105' y='140.503'/>
+<use x='241.567' xlink:href='#g2-115' y='140.503'/>
+<use x='247.636' xlink:href='#g2-98' y='140.503'/>
+<use x='252.244' xlink:href='#g2-101' y='140.503'/>
+<use x='256.008' xlink:href='#g2-116' y='140.503'/>
+<use x='259.066' xlink:href='#g2-116' y='140.503'/>
+<use x='262.124' xlink:href='#g2-101' y='140.503'/>
+<use x='265.887' xlink:href='#g2-114' y='140.503'/>
+<use x='268.779' xlink:href='#g2-41' y='140.503'/>
+</g>
+<path d='M136.149 231.446H376.824V214.453H136.149Z' fill='#ffffff'/>
+<path d='M136.149 231.446H376.824V214.453H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 224.941H142.324V216.972H139.336ZM145.313 224.941H148.301V218.964H145.313Z' fill='#f0e0f0'/>
+<path d='M139.336 224.941H142.324V216.972H139.336ZM145.313 224.941H148.301V218.964H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 84.43)'>
+<use x='185.011' xlink:href='#g2-109' y='140.503'/>
+<use x='191.736' xlink:href='#g2-105' y='140.503'/>
+</g>
+<path d='M163.422 224.941H166.41V216.973H163.422ZM169.398 224.941H172.391V218.965H169.398Z' fill='#e1c2e1'/>
+<path d='M163.422 224.941H166.41V216.972H163.422ZM169.398 224.941H172.391V218.964H169.398Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 83.976)'>
+<use x='208.137' xlink:href='#g2-116' y='140.503'/>
+<use x='211.195' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M185.586 224.941H188.574V216.973H185.586ZM191.563 224.941H194.555V218.965H191.563Z' fill='#d1a3d1'/>
+<path d='M185.586 224.941H188.574V216.972H185.586ZM191.563 224.941H194.555V218.964H191.563Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 84.43)'>
+<use x='229.9' xlink:href='#g2-106' y='140.503'/>
+<use x='232.155' xlink:href='#g2-101' y='140.503'/>
+</g>
+<path d='M206.949 224.941H209.938V216.973H206.949ZM212.926 224.941H215.914V218.965H212.926Z' fill='#c285c2'/>
+<path d='M206.949 224.941H209.938V216.972H206.949ZM212.926 224.941H215.914V218.964H212.926Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 83.47)'>
+<use x='252.061' xlink:href='#g2-115' y='140.503'/>
+<use x='255.307' xlink:href='#g2-110' y='140.503'/>
+</g>
+<path d='M229.91 224.941H232.898V216.973H229.91ZM235.887 224.941H238.875V218.965H235.887Z' fill='#b366b3'/>
+<path d='M229.91 224.941H232.898V216.972H229.91ZM235.887 224.941H238.875V218.964H235.887Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 83.47)'>
+<use x='274.845' xlink:href='#g2-114' y='140.503'/>
+<use x='277.737' xlink:href='#g2-112' y='140.503'/>
+</g>
+<path d='M252.516 224.941H255.504V216.973H252.516ZM258.496 224.941H261.484V218.965H258.496Z' fill='#a447a4'/>
+<path d='M252.516 224.941H255.504V216.972H252.516ZM258.496 224.941H261.484V218.964H258.496Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 84.467)'>
+<use x='303.672' xlink:href='#g2-104' y='140.503'/>
+<use x='308.045' xlink:href='#g2-111' y='140.503'/>
+<use x='312.279' xlink:href='#g2-97' y='140.503'/>
+<use x='316.112' xlink:href='#g2-114' y='140.503'/>
+<use x='319.004' xlink:href='#g2-100' y='140.503'/>
+</g>
+<path d='M287.563 224.941H290.551V216.973H287.563ZM293.543 224.941H296.531V218.965H293.543Z' fill='#942994'/>
+<path d='M287.563 224.941H290.551V216.972H287.563ZM293.543 224.941H296.531V218.964H293.543Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 84.467)'>
+<use x='337.19' xlink:href='#g2-103' y='140.503'/>
+<use x='341.424' xlink:href='#g2-108' y='140.503'/>
+<use x='343.444' xlink:href='#g2-105' y='140.503'/>
+<use x='345.464' xlink:href='#g2-98' y='140.503'/>
+<use x='350.072' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M319.551 224.941H322.539V216.973H319.551ZM325.527 224.941H328.52V218.965H325.527Z' fill='#850a85'/>
+<path d='M319.551 224.941H322.539V216.972H319.551ZM325.527 224.941H328.52V218.964H325.527Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 84.467)'>
+<use x='366.757' xlink:href='#g2-116' y='140.503'/>
+<use x='369.815' xlink:href='#g2-98' y='140.503'/>
+<use x='374.187' xlink:href='#g2-98' y='140.503'/>
+</g>
+<path d='M346.699 224.941H349.688V216.973H346.699ZM352.676 224.941H355.664V218.965H352.676Z' fill='#760076'/>
+<path d='M346.699 224.941H349.688V216.972H346.699ZM352.676 224.941H355.664V218.964H352.676Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.145 84.43)'>
+<use x='393.997' xlink:href='#g2-115' y='140.503'/>
+<use x='397.243' xlink:href='#g2-109' y='140.503'/>
+<use x='403.968' xlink:href='#g2-105' y='140.503'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-spec.svg b/extlib/mimalloc/doc/bench-2020/bench-spec.svg
new file mode 100644 (file)
index 0000000..af2b41b
--- /dev/null
@@ -0,0 +1,713 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='182.025pt' version='1.1' viewBox='52.938 51.674 270.487 182.025' width='270.487pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip5'>
+<path d='M82.148 186.074H301.789V60.828H82.148Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-46' transform='scale(1.6)' xlink:href='#g1-46'/>
+<use id='g2-48' transform='scale(1.6)' xlink:href='#g1-48'/>
+<use id='g2-50' transform='scale(1.6)' xlink:href='#g1-50'/>
+<use id='g2-51' transform='scale(1.6)' xlink:href='#g1-51'/>
+<use id='g2-52' transform='scale(1.6)' xlink:href='#g1-52'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-107' transform='scale(1.6)' xlink:href='#g1-107'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M3.248 -3.457H2.745V-1.963H0.986V-3.457H0.483V0H0.986V-1.634H2.745V0H3.248V-3.457Z' id='g1-72'/>
+<path d='M0.986 -3.457H0.483V0H0.986V-3.457Z' id='g1-73'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.611 -1.714C3.611 -2.745 2.854 -3.562 1.953 -3.562S0.294 -2.745 0.294 -1.714S1.061 0.105 1.953 0.105C2.849 0.105 3.611 -0.687 3.611 -1.714ZM1.953 -0.249C1.35 -0.249 0.797 -0.852 0.797 -1.793C0.797 -2.675 1.355 -3.218 1.953 -3.218S3.108 -2.675 3.108 -1.793C3.108 -0.847 2.555 -0.249 1.953 -0.249Z' id='g1-79'/>
+<path d='M1.868 -1.42C2.511 -1.42 3.083 -1.873 3.083 -2.446C3.083 -2.979 2.555 -3.457 1.833 -3.457H0.488V0H0.991V-1.42H1.868ZM1.709 -3.163C2.271 -3.163 2.63 -2.864 2.63 -2.446C2.63 -2.037 2.291 -1.729 1.709 -1.729H0.976V-3.163H1.709Z' id='g1-80'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M1.968 -1.823L3.228 -3.457H2.685L1.724 -2.182L0.742 -3.457H0.149L1.479 -1.823L0.075 0H0.618L1.724 -1.499L2.854 0H3.447L1.968 -1.823Z' id='g1-88'/>
+<path d='M2.934 -3.238V-3.457H0.369V-3.123H1.41C1.479 -3.123 1.539 -3.128 1.609 -3.128H2.291L0.294 -0.229V0H2.964V-0.354H2.466C1.958 -0.354 1.45 -0.344 0.941 -0.344L2.934 -3.238Z' id='g1-90'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M1.489 -1.355L2.376 -2.212H1.893L0.827 -1.181V-3.457H0.438V0H0.807V-0.697L1.23 -1.106L2.052 0H2.491L1.489 -1.355Z' id='g1-107'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g0-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page5'>
+<path d='M137.059 194.93V186.074M191.969 194.93V186.074M246.879 194.93V186.074M137.059 51.973V60.828M191.969 51.973V60.828M246.879 51.973V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M109.606 190.324V186.074M164.516 190.324V186.074M219.422 190.324V186.074M274.332 190.324V186.074M109.606 56.574V60.828M164.516 56.574V60.828M219.422 56.574V60.828M274.332 56.574V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 186.074H86.402M82.148 154.762H86.402M82.148 123.449H86.402M82.148 92.141H86.402M82.148 60.828H86.402M301.789 186.074H297.535M301.789 154.762H297.535M301.789 123.449H297.535M301.789 92.141H297.535M301.789 60.828H297.535' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 186.074V60.828H301.789V186.074H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -18.291 59.571)'>
+<use x='114.487' xlink:href='#g2-54' y='140.503'/>
+<use x='118.721' xlink:href='#g2-48' y='140.503'/>
+<use x='122.955' xlink:href='#g2-50' y='140.503'/>
+<use x='127.189' xlink:href='#g2-46' y='140.503'/>
+<use x='129.541' xlink:href='#g2-103' y='140.503'/>
+<use x='133.776' xlink:href='#g2-99' y='140.503'/>
+<use x='137.539' xlink:href='#g2-99' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 27.05 59.571)'>
+<use x='114.487' xlink:href='#g2-54' y='140.503'/>
+<use x='118.721' xlink:href='#g2-50' y='140.503'/>
+<use x='122.955' xlink:href='#g2-48' y='140.503'/>
+<use x='127.189' xlink:href='#g2-46' y='140.503'/>
+<use x='129.541' xlink:href='#g2-111' y='140.503'/>
+<use x='133.776' xlink:href='#g2-109' y='140.503'/>
+<use x='140.501' xlink:href='#g2-110' y='140.503'/>
+<use x='144.873' xlink:href='#g2-101' y='140.503'/>
+<use x='148.637' xlink:href='#g2-116' y='140.503'/>
+<use x='151.695' xlink:href='#g2-112' y='140.503'/>
+<use x='156.067' xlink:href='#g2-112' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 78.694 59.571)'>
+<use x='114.487' xlink:href='#g2-54' y='140.503'/>
+<use x='118.721' xlink:href='#g2-50' y='140.503'/>
+<use x='122.955' xlink:href='#g2-51' y='140.503'/>
+<use x='127.189' xlink:href='#g2-46' y='140.503'/>
+<use x='129.541' xlink:href='#g2-120' y='140.503'/>
+<use x='133.444' xlink:href='#g2-97' y='140.503'/>
+<use x='137.512' xlink:href='#g2-108' y='140.503'/>
+<use x='139.532' xlink:href='#g2-97' y='140.503'/>
+<use x='143.6' xlink:href='#g2-110' y='140.503'/>
+<use x='147.973' xlink:href='#g2-99' y='140.503'/>
+<use x='151.736' xlink:href='#g2-98' y='140.503'/>
+<use x='156.109' xlink:href='#g2-109' y='140.503'/>
+<use x='162.834' xlink:href='#g2-107' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 134.081 59.571)'>
+<use x='114.487' xlink:href='#g2-54' y='140.503'/>
+<use x='118.721' xlink:href='#g2-52' y='140.503'/>
+<use x='122.955' xlink:href='#g2-56' y='140.503'/>
+<use x='127.189' xlink:href='#g2-46' y='140.503'/>
+<use x='129.541' xlink:href='#g2-101' y='140.503'/>
+<use x='133.305' xlink:href='#g2-120' y='140.503'/>
+<use x='137.207' xlink:href='#g2-99' y='140.503'/>
+<use x='140.971' xlink:href='#g2-104' y='140.503'/>
+<use x='145.344' xlink:href='#g2-97' y='140.503'/>
+<use x='149.412' xlink:href='#g2-110' y='140.503'/>
+<use x='153.784' xlink:href='#g2-103' y='140.503'/>
+<use x='158.018' xlink:href='#g2-101' y='140.503'/>
+<use x='161.782' xlink:href='#g2-50' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 47.205)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.894)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-53' y='140.503'/>
+<use x='121.25' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -15.418)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -46.729)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-53' y='140.503'/>
+<use x='121.25' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.041)'>
+<use x='114.487' xlink:href='#g1-50' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-120' y='140.503'/>
+</g>
+<path clip-path='url(#clip5)' d='M82.148 123.449H301.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M87.063 186.074H90.301V123.449H87.063ZM141.973 186.074H145.211V123.449H141.973ZM196.883 186.074H200.121V123.449H196.883ZM251.793 186.074H255.031V123.449H251.793Z' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M87.063 186.074H90.301V123.449H87.063ZM141.973 186.074H145.211V123.449H141.973ZM196.883 186.074H200.121V123.449H196.883ZM251.793 186.074H255.031V123.449H251.793Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M88.684 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M86.691 123.449H90.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M88.684 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M86.691 123.449H90.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M143.594 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M141.602 123.449H145.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M143.594 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M141.602 123.449H145.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M198.5 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M196.511 123.449H200.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M198.5 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M196.511 123.449H200.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M253.41 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M251.418 123.449H255.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M253.41 123.449V123.449' fill='#e0e0f0'/>
+<path clip-path='url(#clip5)' d='M251.418 123.449H255.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M92.293 186.074H95.531V103.535H92.293ZM147.203 186.074H150.441V125.77H147.203ZM202.113 186.074H205.352V124.203H202.113ZM257.024 186.074H260.262V123.074H257.024Z' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M92.293 186.074H95.531V103.535H92.293ZM147.203 186.074H150.441V125.77H147.203ZM202.113 186.074H205.352V124.203H202.113ZM257.024 186.074H260.262V123.074H257.024Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M93.914 103.535V103.535' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M91.922 103.535H95.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M93.914 103.535V103.535' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M91.922 103.535H95.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M148.824 125.77V125.77' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M146.832 125.77H150.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M148.824 125.77V125.77' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M146.832 125.77H150.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M203.731 124.203V124.203' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M201.742 124.203H205.727' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M203.731 124.203V124.203' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M201.742 124.203H205.727' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M258.641 123.074V123.074' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M256.648 123.074H260.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M258.641 123.074V123.074' fill='#c2c2e1'/>
+<path clip-path='url(#clip5)' d='M256.648 123.074H260.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M97.524 186.074H100.762V123.324H97.524ZM152.434 186.074H155.672V123.828H152.434ZM207.344 186.074H210.582V124.203H207.344ZM262.254 186.074H265.492V123.137H262.254Z' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M97.524 186.074H100.762V123.324H97.524ZM152.434 186.074H155.672V123.828H152.434ZM207.344 186.074H210.582V124.203H207.344ZM262.254 186.074H265.492V123.137H262.254Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M99.145 123.324V123.324' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M97.152 123.325H101.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M99.145 123.324V123.324' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M97.152 123.325H101.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M154.055 123.828V123.828' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M152.063 123.829H156.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M154.055 123.828V123.828' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M152.063 123.829H156.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M208.961 124.203V124.203' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M206.972 124.203H210.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M208.961 124.203V124.203' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M206.972 124.203H210.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M263.871 123.137V123.137' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M261.879 123.137H265.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M263.871 123.137V123.137' fill='#a3a3d1'/>
+<path clip-path='url(#clip5)' d='M261.879 123.137H265.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M102.754 186.074H105.992V123.449H102.754ZM157.664 186.074H160.902V125.77H157.664ZM212.574 186.074H215.813V125.391H212.574ZM267.484 186.074H270.723V122.449H267.484Z' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M102.754 186.074H105.992V123.449H102.754ZM157.664 186.074H160.902V125.77H157.664ZM212.574 186.074H215.813V125.391H212.574ZM267.484 186.074H270.723V122.449H267.484Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M104.375 123.449V123.449' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M102.383 123.449H106.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M104.375 123.449V123.449' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M102.383 123.449H106.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M159.285 125.77V125.77' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M157.293 125.77H161.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M159.285 125.77V125.77' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M157.293 125.77H161.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M214.192 125.391V125.391' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M212.203 125.39H216.188' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M214.192 125.391V125.391' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M212.203 125.39H216.188' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M269.102 122.449V122.449' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M267.109 122.449H271.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M269.102 122.449V122.449' fill='#8585c2'/>
+<path clip-path='url(#clip5)' d='M267.109 122.449H271.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M107.984 186.074H111.223V122.699H107.984ZM162.895 186.074H166.133V117.188H162.895ZM217.805 186.074H221.043V104.727H217.805ZM272.715 186.074H275.953V122.762H272.715Z' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M107.984 186.074H111.223V122.699H107.984ZM162.895 186.074H166.133V117.188H162.895ZM217.805 186.074H221.043V104.727H217.805ZM272.715 186.074H275.953V122.762H272.715Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M109.606 122.699V122.699' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M107.613 122.699H111.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M109.606 122.699V122.699' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M107.613 122.699H111.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M164.516 117.188V117.188' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M162.524 117.188H166.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M164.516 117.188V117.188' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M162.524 117.188H166.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M219.422 104.727V104.727' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M217.433 104.727H221.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M219.422 104.727V104.727' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M217.433 104.727H221.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M274.332 122.762V122.762' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M272.34 122.762H276.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M274.332 122.762V122.762' fill='#6666b3'/>
+<path clip-path='url(#clip5)' d='M272.34 122.762H276.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M113.215 186.074H116.453V123.574H113.215ZM168.125 186.074H171.363V119.696H168.125ZM223.035 186.074H226.274V122.637H223.035ZM277.945 186.074H281.184V122.449H277.945Z' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M113.215 186.074H116.453V123.574H113.215ZM168.125 186.074H171.363V119.696H168.125ZM223.035 186.074H226.274V122.637H223.035ZM277.945 186.074H281.184V122.449H277.945Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M114.836 123.574V123.574' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M112.844 123.574H116.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M114.836 123.574V123.574' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M112.844 123.574H116.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M169.746 119.696V119.696' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M167.754 119.695H171.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M169.746 119.696V119.696' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M167.754 119.695H171.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M224.652 122.637V122.637' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M222.664 122.637H226.649' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M224.652 122.637V122.637' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M222.664 122.637H226.649' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M279.563 122.449V122.449' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M277.57 122.449H281.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M279.563 122.449V122.449' fill='#4747a4'/>
+<path clip-path='url(#clip5)' d='M277.57 122.449H281.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M118.445 186.074H121.684V122.574H118.445ZM173.356 186.074H176.594V117.25H173.356ZM228.266 186.074H231.504V105.477H228.266ZM283.176 186.074H286.414V121.887H283.176Z' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M118.445 186.074H121.684V122.574H118.445ZM173.356 186.074H176.594V117.25H173.356ZM228.266 186.074H231.504V105.477H228.266ZM283.176 186.074H286.414V121.887H283.176Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M120.066 122.574V122.574' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M118.074 122.574H122.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M120.066 122.574V122.574' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M118.074 122.574H122.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M174.977 117.25V117.25' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M172.985 117.25H176.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M174.977 117.25V117.25' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M172.985 117.25H176.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M229.883 105.477V105.477' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M227.894 105.477H231.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M229.883 105.477V105.477' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M227.894 105.477H231.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M284.793 121.887V121.887' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M282.801 121.886H286.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M284.793 121.887V121.887' fill='#292994'/>
+<path clip-path='url(#clip5)' d='M282.801 121.886H286.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M123.676 186.074H126.914V106.606H123.676ZM178.586 186.074H181.824V122.699H178.586ZM233.496 186.074H236.734V122.449H233.496ZM288.406 186.074H291.645V122.012H288.406Z' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M123.676 186.074H126.914V106.606H123.676ZM178.586 186.074H181.824V122.699H178.586ZM233.496 186.074H236.734V122.449H233.496ZM288.406 186.074H291.645V122.012H288.406Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M125.297 106.606V106.606' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M123.305 106.605H127.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M125.297 106.606V106.606' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M123.305 106.605H127.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M180.207 122.699V122.699' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M178.215 122.699H182.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M180.207 122.699V122.699' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M178.215 122.699H182.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M235.113 122.449V122.449' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M233.125 122.449H237.11' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M235.113 122.449V122.449' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M233.125 122.449H237.11' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M290.024 122.012V122.012' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M288.031 122.012H292.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M290.024 122.012V122.012' fill='#0a0a85'/>
+<path clip-path='url(#clip5)' d='M288.031 122.012H292.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M128.906 186.074H132.145V120.633H128.906ZM183.817 186.074H187.055V122.074H183.817ZM238.727 186.074H241.965V119.696H238.727ZM293.637 186.074H296.875V123.387H293.637Z' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M128.906 186.074H132.145V120.633H128.906ZM183.817 186.074H187.055V122.074H183.817ZM238.727 186.074H241.965V119.696H238.727ZM293.637 186.074H296.875V123.387H293.637Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M130.527 120.633V120.633' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M128.535 120.633H132.52' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M130.527 120.633V120.633' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M128.535 120.633H132.52' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M185.438 122.074V122.074' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M183.446 122.074H187.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M185.438 122.074V122.074' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M183.446 122.074H187.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M240.344 119.696V119.696' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M238.355 119.695H242.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M240.344 119.696V119.696' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M238.355 119.695H242.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M295.254 123.387V123.387' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M293.262 123.387H297.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M295.254 123.387V123.387' fill='#000076'/>
+<path clip-path='url(#clip5)' d='M293.262 123.387H297.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip5)' d='M233.301 233.301H301.59V211.324H233.301Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 122.136 88.837)'>
+<use x='114.487' xlink:href='#g1-72' y='129.265'/>
+<use x='118.223' xlink:href='#g1-80' y='129.265'/>
+<use x='121.604' xlink:href='#g1-45' y='129.265'/>
+<use x='123.368' xlink:href='#g1-90' y='129.265'/>
+<use x='126.603' xlink:href='#g1-52' y='129.265'/>
+<use x='129.249' xlink:href='#g1-45' y='129.265'/>
+<use x='131.013' xlink:href='#g1-71' y='129.265'/>
+<use x='134.542' xlink:href='#g1-52' y='129.265'/>
+<use x='137.188' xlink:href='#g1-44' y='129.265'/>
+<use x='140.423' xlink:href='#g1-49' y='129.265'/>
+<use x='143.069' xlink:href='#g1-54' y='129.265'/>
+<use x='145.715' xlink:href='#g1-71' y='129.265'/>
+<use x='149.244' xlink:href='#g1-98' y='129.265'/>
+<use x='114.487' xlink:href='#g1-56' y='134.884'/>
+<use x='117.133' xlink:href='#g1-45' y='134.884'/>
+<use x='118.897' xlink:href='#g1-99' y='134.884'/>
+<use x='121.25' xlink:href='#g1-111' y='134.884'/>
+<use x='123.749' xlink:href='#g1-114' y='134.884'/>
+<use x='125.556' xlink:href='#g1-101' y='134.884'/>
+<use x='129.673' xlink:href='#g1-73' y='134.884'/>
+<use x='131.143' xlink:href='#g1-110' y='134.884'/>
+<use x='133.876' xlink:href='#g1-116' y='134.884'/>
+<use x='135.787' xlink:href='#g1-101' y='134.884'/>
+<use x='138.14' xlink:href='#g1-108' y='134.884'/>
+<use x='141.166' xlink:href='#g1-88' y='134.884'/>
+<use x='144.695' xlink:href='#g1-69' y='134.884'/>
+<use x='147.869' xlink:href='#g1-79' y='134.884'/>
+<use x='151.778' xlink:href='#g1-78' y='134.884'/>
+<use x='157.278' xlink:href='#g1-64' y='134.884'/>
+<use x='160.807' xlink:href='#g1-50' y='134.884'/>
+<use x='163.453' xlink:href='#g1-46' y='134.884'/>
+<use x='164.923' xlink:href='#g1-55' y='134.884'/>
+<use x='167.57' xlink:href='#g1-71' y='134.884'/>
+<use x='171.098' xlink:href='#g1-104' y='134.884'/>
+<use x='173.831' xlink:href='#g1-122' y='134.884'/>
+<use x='114.487' xlink:href='#g1-85' y='140.503'/>
+<use x='118.119' xlink:href='#g1-98' y='140.503'/>
+<use x='120.852' xlink:href='#g1-117' y='140.503'/>
+<use x='123.585' xlink:href='#g1-110' y='140.503'/>
+<use x='126.317' xlink:href='#g1-116' y='140.503'/>
+<use x='128.229' xlink:href='#g1-117' y='140.503'/>
+<use x='132.726' xlink:href='#g1-49' y='140.503'/>
+<use x='135.372' xlink:href='#g1-56' y='140.503'/>
+<use x='138.018' xlink:href='#g1-46' y='140.503'/>
+<use x='139.489' xlink:href='#g1-48' y='140.503'/>
+<use x='142.135' xlink:href='#g1-52' y='140.503'/>
+<use x='144.781' xlink:href='#g1-46' y='140.503'/>
+<use x='146.252' xlink:href='#g1-49' y='140.503'/>
+<use x='148.898' xlink:href='#g1-44' y='140.503'/>
+<use x='152.132' xlink:href='#g1-71' y='140.503'/>
+<use x='155.661' xlink:href='#g1-67' y='140.503'/>
+<use x='159.042' xlink:href='#g1-67' y='140.503'/>
+<use x='164.188' xlink:href='#g1-55' y='140.503'/>
+<use x='166.834' xlink:href='#g1-46' y='140.503'/>
+<use x='168.305' xlink:href='#g1-52' y='140.503'/>
+<use x='170.951' xlink:href='#g1-46' y='140.503'/>
+<use x='172.421' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -50.186 231.913)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 4.724 231.913)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.633 231.913)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 114.543 231.913)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -44.955 211.999)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-51' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 9.954 234.23)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.864 232.665)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 119.773 231.537)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -39.725 231.788)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 15.185 232.289)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 70.094 232.665)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 125.004 231.6)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -34.494 231.913)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 20.415 234.23)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 75.325 233.854)'>
+<use x='114.487' xlink:href='#g1-48' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-57' y='140.503'/>
+<use x='121.25' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.234 230.911)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.264 231.162)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 25.646 225.651)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-49' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 80.555 213.189)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-51' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.465 231.224)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.033 232.038)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 30.876 228.156)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.786 231.099)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.695 230.911)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -18.803 231.036)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.107 225.713)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-49' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 91.016 213.94)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-50' y='140.503'/>
+<use x='121.25' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.926 230.348)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -13.572 215.068)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-50' y='140.503'/>
+<use x='121.25' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 41.337 231.162)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 96.247 230.911)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.156 230.473)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -8.342 229.095)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-52' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 46.568 230.535)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 101.477 228.156)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.387 231.85)'>
+<use x='114.487' xlink:href='#g1-49' y='140.503'/>
+<use x='117.133' xlink:href='#g1-46' y='140.503'/>
+<use x='118.603' xlink:href='#g1-48' y='140.503'/>
+<use x='121.25' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -81.143 293.197)'>
+<use x='114.487' xlink:href='#g0-82' y='140.503'/>
+<use x='120.457' xlink:href='#g0-101' y='140.503'/>
+<use x='124.553' xlink:href='#g0-108' y='140.503'/>
+<use x='126.753' xlink:href='#g0-97' y='140.503'/>
+<use x='131.181' xlink:href='#g0-116' y='140.503'/>
+<use x='134.509' xlink:href='#g0-105' y='140.503'/>
+<use x='136.709' xlink:href='#g0-118' y='140.503'/>
+<use x='140.957' xlink:href='#g0-101' y='140.503'/>
+<use x='148.124' xlink:href='#g0-116' y='140.503'/>
+<use x='151.452' xlink:href='#g0-105' y='140.503'/>
+<use x='153.652' xlink:href='#g0-109' y='140.503'/>
+<use x='160.972' xlink:href='#g0-101' y='140.503'/>
+<use x='168.139' xlink:href='#g2-40' y='140.503'/>
+<use x='171.432' xlink:href='#g2-108' y='140.503'/>
+<use x='173.453' xlink:href='#g2-111' y='140.503'/>
+<use x='177.452' xlink:href='#g2-119' y='140.503'/>
+<use x='183' xlink:href='#g2-101' y='140.503'/>
+<use x='186.764' xlink:href='#g2-114' y='140.503'/>
+<use x='192.479' xlink:href='#g2-105' y='140.503'/>
+<use x='194.499' xlink:href='#g2-115' y='140.503'/>
+<use x='200.568' xlink:href='#g2-98' y='140.503'/>
+<use x='205.176' xlink:href='#g2-101' y='140.503'/>
+<use x='208.94' xlink:href='#g2-116' y='140.503'/>
+<use x='211.998' xlink:href='#g2-116' y='140.503'/>
+<use x='215.056' xlink:href='#g2-101' y='140.503'/>
+<use x='218.819' xlink:href='#g2-114' y='140.503'/>
+<use x='221.711' xlink:href='#g2-41' y='140.503'/>
+</g>
+<path d='M82.348 231.446H323.027V214.453H82.348Z' fill='#ffffff'/>
+<path d='M82.348 231.446H323.027V214.453H82.348Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M85.535 224.941H88.523V216.972H85.535ZM91.516 224.941H94.504V218.964H91.516Z' fill='#e0e0f0'/>
+<path d='M85.535 224.941H88.523V216.972H85.535ZM91.516 224.941H94.504V218.964H91.516Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 84.43)'>
+<use x='131.213' xlink:href='#g2-109' y='140.503'/>
+<use x='137.938' xlink:href='#g2-105' y='140.503'/>
+</g>
+<path d='M109.625 224.941H112.613V216.973H109.625ZM115.602 224.941H118.59V218.965H115.602Z' fill='#c2c2e1'/>
+<path d='M109.625 224.941H112.613V216.972H109.625ZM115.602 224.941H118.59V218.964H115.602Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 83.976)'>
+<use x='154.339' xlink:href='#g2-116' y='140.503'/>
+<use x='157.397' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M131.789 224.941H134.777V216.973H131.789ZM137.766 224.941H140.754V218.965H137.766Z' fill='#a3a3d1'/>
+<path d='M131.789 224.941H134.777V216.972H131.789ZM137.766 224.941H140.754V218.964H137.766Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 84.43)'>
+<use x='176.102' xlink:href='#g2-106' y='140.503'/>
+<use x='178.357' xlink:href='#g2-101' y='140.503'/>
+</g>
+<path d='M153.152 224.941H156.141V216.973H153.152ZM159.129 224.941H162.117V218.965H159.129Z' fill='#8585c2'/>
+<path d='M153.152 224.941H156.141V216.972H153.152ZM159.129 224.941H162.117V218.964H159.129Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 83.47)'>
+<use x='198.263' xlink:href='#g2-115' y='140.503'/>
+<use x='201.509' xlink:href='#g2-110' y='140.503'/>
+</g>
+<path d='M176.113 224.941H179.102V216.973H176.113ZM182.09 224.941H185.078V218.965H182.09Z' fill='#6666b3'/>
+<path d='M176.113 224.941H179.102V216.972H176.113ZM182.09 224.941H185.078V218.964H182.09Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 83.47)'>
+<use x='221.047' xlink:href='#g2-114' y='140.503'/>
+<use x='223.939' xlink:href='#g2-112' y='140.503'/>
+</g>
+<path d='M198.719 224.941H201.707V216.973H198.719ZM204.695 224.941H207.684V218.965H204.695Z' fill='#4747a4'/>
+<path d='M198.719 224.941H201.707V216.972H198.719ZM204.695 224.941H207.684V218.964H204.695Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 84.467)'>
+<use x='249.874' xlink:href='#g2-104' y='140.503'/>
+<use x='254.246' xlink:href='#g2-111' y='140.503'/>
+<use x='258.481' xlink:href='#g2-97' y='140.503'/>
+<use x='262.314' xlink:href='#g2-114' y='140.503'/>
+<use x='265.206' xlink:href='#g2-100' y='140.503'/>
+</g>
+<path d='M233.766 224.941H236.754V216.973H233.766ZM239.742 224.941H242.731V218.965H239.742Z' fill='#292994'/>
+<path d='M233.766 224.941H236.754V216.972H233.766ZM239.742 224.941H242.731V218.964H239.742Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 84.467)'>
+<use x='283.392' xlink:href='#g2-103' y='140.503'/>
+<use x='287.626' xlink:href='#g2-108' y='140.503'/>
+<use x='289.646' xlink:href='#g2-105' y='140.503'/>
+<use x='291.666' xlink:href='#g2-98' y='140.503'/>
+<use x='296.274' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M265.754 224.941H268.742V216.973H265.754ZM271.73 224.941H274.719V218.965H271.73Z' fill='#0a0a85'/>
+<path d='M265.754 224.941H268.742V216.972H265.754ZM271.73 224.941H274.719V218.964H271.73Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 84.467)'>
+<use x='312.959' xlink:href='#g2-116' y='140.503'/>
+<use x='316.017' xlink:href='#g2-98' y='140.503'/>
+<use x='320.389' xlink:href='#g2-98' y='140.503'/>
+</g>
+<path d='M292.898 224.941H295.887V216.973H292.898ZM298.879 224.941H301.867V218.965H298.879Z' fill='#000076'/>
+<path d='M292.898 224.941H295.887V216.972H292.898ZM298.879 224.941H301.867V218.964H298.879Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.145 84.43)'>
+<use x='340.198' xlink:href='#g2-115' y='140.503'/>
+<use x='343.444' xlink:href='#g2-109' y='140.503'/>
+<use x='350.169' xlink:href='#g2-105' y='140.503'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-z4-1.svg b/extlib/mimalloc/doc/bench-2020/bench-z4-1.svg
new file mode 100644 (file)
index 0000000..dacd8ab
--- /dev/null
@@ -0,0 +1,890 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='164.687pt' version='1.1' viewBox='52.938 54.996 381.625 164.687' width='381.625pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip3'>
+<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-102' transform='scale(1.6)' xlink:href='#g1-102'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M0.946 -1.898H1.514V-2.212H0.932V-2.785C0.932 -3.128 1.245 -3.178 1.41 -3.178C1.514 -3.178 1.649 -3.163 1.833 -3.093V-3.457C1.704 -3.487 1.549 -3.507 1.415 -3.507C0.902 -3.507 0.528 -3.138 0.528 -2.645V-2.212H0.144V-1.898H0.528V0H0.946V-1.898Z' id='g1-102'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g0-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page3'>
+<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 33.989)'>
+<use x='114.487' xlink:href='#g2-99' y='183.949'/>
+<use x='118.25' xlink:href='#g2-102' y='183.949'/>
+<use x='120.838' xlink:href='#g2-114' y='183.949'/>
+<use x='123.73' xlink:href='#g2-97' y='183.949'/>
+<use x='127.798' xlink:href='#g2-99' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 41.401 33.989)'>
+<use x='114.487' xlink:href='#g2-101' y='183.949'/>
+<use x='118.25' xlink:href='#g2-115' y='183.949'/>
+<use x='121.497' xlink:href='#g2-112' y='183.949'/>
+<use x='125.634' xlink:href='#g2-114' y='183.949'/>
+<use x='128.526' xlink:href='#g2-101' y='183.949'/>
+<use x='132.29' xlink:href='#g2-115' y='183.949'/>
+<use x='135.536' xlink:href='#g2-115' y='183.949'/>
+<use x='138.782' xlink:href='#g2-111' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 103.095 33.989)'>
+<use x='114.487' xlink:href='#g2-98' y='183.949'/>
+<use x='118.859' xlink:href='#g2-97' y='183.949'/>
+<use x='122.692' xlink:href='#g2-114' y='183.949'/>
+<use x='125.584' xlink:href='#g2-110' y='183.949'/>
+<use x='129.957' xlink:href='#g2-101' y='183.949'/>
+<use x='133.72' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 162.903 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-101' y='183.949'/>
+<use x='120.271' xlink:href='#g2-97' y='183.949'/>
+<use x='124.339' xlink:href='#g2-110' y='183.949'/>
+<use x='128.711' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 223.526 33.989)'>
+<use x='114.487' xlink:href='#g2-114' y='183.949'/>
+<use x='117.379' xlink:href='#g2-101' y='183.949'/>
+<use x='121.142' xlink:href='#g2-100' y='183.949'/>
+<use x='125.515' xlink:href='#g2-105' y='183.949'/>
+<use x='127.535' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 277.054 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-97' y='183.949'/>
+<use x='120.34' xlink:href='#g2-114' y='183.949'/>
+<use x='123.232' xlink:href='#g2-115' y='183.949'/>
+<use x='126.478' xlink:href='#g2-111' y='183.949'/>
+<use x='130.712' xlink:href='#g2-110' y='183.949'/>
+<use x='135.085' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 21.624)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.688)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.999)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -72.311)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.622)'>
+<use x='114.487' xlink:href='#g1-50' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<path clip-path='url(#clip3)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M86.328 203.937H89.566V141.316H86.328ZM144.996 203.937H148.234V141.316H144.996ZM203.668 203.937H206.902V141.316H203.668ZM262.336 203.937H265.574V141.316H262.336ZM321.004 203.937H324.242V141.316H321.004ZM379.672 203.937H382.91V141.316H379.672Z' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M86.328 203.937H89.566V141.316H86.328ZM144.996 203.937H148.234V141.316H144.996ZM203.668 203.937H206.902V141.316H203.668ZM262.336 203.937H265.574V141.316H262.336ZM321.004 203.937H324.242V141.316H321.004ZM379.672 203.937H382.91V141.316H379.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M87.949 141.316V141.004' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M87.949 141.316V141.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M85.953 141.004H89.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M87.949 141.316V141.629' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M87.949 141.316V141.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M89.941 141.629H85.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M146.617 141.316V138.937' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M146.617 141.316V138.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M144.625 138.938H148.61' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M146.617 141.316V143.695' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M146.617 141.316V143.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M148.61 143.695H144.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M205.285 141.316V141.066' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M205.285 141.316V141.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M203.293 141.067H207.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M205.285 141.316V141.566' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M205.285 141.316V141.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M207.278 141.567H203.293' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M263.953 141.316V141.066' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M263.953 141.316V141.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M261.961 141.067H265.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M263.953 141.316V141.566' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M263.953 141.316V141.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M265.949 141.567H261.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M322.625 141.316V140.812' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M322.625 141.316V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M320.629 140.812H324.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M322.625 141.316V141.816' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M322.625 141.316V141.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M324.617 141.816H320.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M381.293 141.316V140' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M381.293 141.316V140' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M379.301 140H383.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M381.293 141.316V142.629' fill='#e0e0f0'/>
+<path clip-path='url(#clip3)' d='M381.293 141.316V142.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M383.285 142.629H379.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M91.559 203.937H94.797V139.562H91.559ZM150.227 203.937H153.465V138.621H150.227ZM208.899 203.937H212.133V141.441H208.899ZM267.567 203.937H270.805V138.683H267.567ZM326.234 203.937H329.473V137.871H326.234ZM384.902 203.937H388.141V129.855H384.902Z' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M91.559 203.937H94.797V139.562H91.559ZM150.227 203.937H153.465V138.621H150.227ZM208.899 203.937H212.133V141.441H208.899ZM267.567 203.937H270.805V138.683H267.567ZM326.234 203.937H329.473V137.871H326.234ZM384.902 203.937H388.141V129.855H384.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M93.18 139.562V139.562' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M91.184 139.563H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M93.18 139.562V139.562' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M91.184 139.563H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M151.848 138.621V138.621' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M149.855 138.621H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M151.848 138.621V138.621' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M149.855 138.621H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M210.516 141.441V141.254' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M210.516 141.441V141.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M208.523 141.254H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M210.516 141.441V141.629' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M210.516 141.441V141.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M212.508 141.629H208.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M269.184 138.683V138.621' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M269.184 138.683V138.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M267.191 138.621H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M269.184 138.683V138.746' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M269.184 138.683V138.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M271.179 138.746H267.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M327.856 137.871V137.558' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M327.856 137.871V137.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M325.859 137.559H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M327.856 137.871V138.183' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M327.856 137.871V138.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M329.847 138.183H325.863' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M386.524 129.855V129.543' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M386.524 129.855V129.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M384.531 129.543H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M386.524 129.855V130.168' fill='#c2c2e1'/>
+<path clip-path='url(#clip3)' d='M386.524 129.855V130.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M388.515 130.168H384.531' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M96.789 203.937H100.027V138.746H96.789ZM155.457 203.937H158.695V135.867H155.457ZM214.129 203.937H217.363V141.379H214.129ZM272.797 203.937H276.035V140.25H272.797ZM331.465 203.937H334.703V130.918H331.465ZM390.133 203.937H393.371V115.515H390.133Z' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M96.789 203.937H100.027V138.746H96.789ZM155.457 203.937H158.695V135.867H155.457ZM214.129 203.937H217.363V141.379H214.129ZM272.797 203.937H276.035V140.25H272.797ZM331.465 203.937H334.703V130.918H331.465ZM390.133 203.937H393.371V115.515H390.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M98.41 138.746V138.558' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M98.41 138.746V138.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M96.414 138.559H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M98.41 138.746V138.937' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M98.41 138.746V138.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M100.402 138.938H96.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M157.078 135.867V135.867' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M155.086 135.867H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M157.078 135.867V135.867' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M155.086 135.867H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M215.746 141.379V141.129' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M215.746 141.379V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M213.754 141.128H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M215.746 141.379V141.629' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M215.746 141.379V141.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M217.739 141.629H213.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M274.414 140.25V140.187' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M274.414 140.25V140.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M272.422 140.187H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M274.414 140.25V140.312' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M274.414 140.25V140.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M276.41 140.312H272.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M333.086 130.918V130.73' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M333.086 130.918V130.73' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M331.09 130.73H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M333.086 130.918V131.109' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M333.086 130.918V131.109' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M335.078 131.11H331.094' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M391.754 115.515V114.636' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M391.754 115.515V114.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M389.762 114.637H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M391.754 115.515V116.39' fill='#a3a3d1'/>
+<path clip-path='url(#clip3)' d='M391.754 115.515V116.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M393.746 116.39H389.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M102.02 203.937H105.258V130.293H102.02ZM160.688 203.937H163.926V133.176H160.688ZM219.359 203.937H222.594V141.066H219.359ZM278.027 203.937H281.266V139.312H278.027ZM336.695 203.937H339.934V136.679H336.695ZM395.363 203.937H398.602V96.789H395.363Z' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M102.02 203.937H105.258V130.293H102.02ZM160.688 203.937H163.926V133.176H160.688ZM219.359 203.937H222.594V141.066H219.359ZM278.027 203.937H281.266V139.312H278.027ZM336.695 203.937H339.934V136.679H336.695ZM395.363 203.937H398.602V96.789H395.363Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M103.641 130.293V129.98' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M103.641 130.293V129.98' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M101.644 129.981H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M103.641 130.293V130.605' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M103.641 130.293V130.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M105.633 130.606H101.648' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M162.309 133.176V133.176' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M160.316 133.176H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M162.309 133.176V133.176' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M160.316 133.176H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M220.977 141.066V140.941' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M220.977 141.066V140.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M218.984 140.942H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M220.977 141.066V141.191' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M220.977 141.066V141.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M222.969 141.191H218.984' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M279.645 139.312V139.125' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M279.645 139.312V139.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M277.652 139.125H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M279.645 139.312V139.5' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M279.645 139.312V139.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M281.64 139.5H277.652' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M338.317 136.679V136.554' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M338.317 136.679V136.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M336.32 136.555H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M338.317 136.679V136.804' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M338.317 136.679V136.804' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M340.308 136.804H336.324' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M396.984 96.789V96.164' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M396.984 96.789V96.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M394.992 96.164H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M396.984 96.789V97.418' fill='#8585c2'/>
+<path clip-path='url(#clip3)' d='M396.984 96.789V97.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M398.976 97.418H394.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M107.25 203.937H110.488V138.621H107.25ZM165.918 203.937H169.156V137.683H165.918ZM224.59 203.937H227.824V141.254H224.59ZM283.258 203.937H286.496V131.859H283.258ZM341.926 203.937H345.164V132.988H341.926ZM400.594 203.937H403.832V124.844H400.594Z' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M107.25 203.937H110.488V138.621H107.25ZM165.918 203.937H169.156V137.683H165.918ZM224.59 203.937H227.824V141.254H224.59ZM283.258 203.937H286.496V131.859H283.258ZM341.926 203.937H345.164V132.988H341.926ZM400.594 203.937H403.832V124.844H400.594Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M108.871 138.621V138.433' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M108.871 138.621V138.433' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M106.875 138.434H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M108.871 138.621V138.808' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M108.871 138.621V138.808' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M110.864 138.808H106.879' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M167.539 137.683V136.429' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M167.539 137.683V136.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M165.547 136.43H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M167.539 137.683V138.937' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M167.539 137.683V138.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M169.532 138.938H165.547' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M226.207 141.254V141.066' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M226.207 141.254V141.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M224.215 141.067H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M226.207 141.254V141.441' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M226.207 141.254V141.441' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M228.2 141.442H224.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M284.875 131.859V131.609' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M284.875 131.859V131.609' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M282.883 131.61H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M284.875 131.859V132.109' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M284.875 131.859V132.109' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M286.868 132.11H282.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M343.547 132.988V132.988' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M341.551 132.988H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M343.547 132.988V132.988' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M341.551 132.988H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M402.215 124.844V124.844' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M400.223 124.843H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M402.215 124.844V124.844' fill='#6666b3'/>
+<path clip-path='url(#clip3)' d='M400.223 124.843H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M112.481 203.937H115.719V136.179H112.481ZM171.149 203.937H174.387V133.176H171.149ZM229.82 203.937H233.055V140.941H229.82ZM288.488 203.937H291.727V134.051H288.488ZM347.156 203.937H350.395V109.129H347.156ZM405.824 203.937H409.063V123.469H405.824Z' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M112.481 203.937H115.719V136.179H112.481ZM171.149 203.937H174.387V133.176H171.149ZM229.82 203.937H233.055V140.941H229.82ZM288.488 203.937H291.727V134.051H288.488ZM347.156 203.937H350.395V109.129H347.156ZM405.824 203.937H409.063V123.469H405.824Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M114.098 136.179V135.867' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M114.098 136.179V135.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M112.105 135.867H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M114.098 136.179V136.492' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M114.098 136.179V136.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M116.094 136.492H112.109' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M172.77 133.176V133.176' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M170.777 133.176H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M172.77 133.176V133.176' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M170.777 133.176H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M231.438 140.941V140.687' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M231.438 140.941V140.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M229.445 140.687H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M231.438 140.941V141.191' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M231.438 140.941V141.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M233.43 141.191H229.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M290.106 134.051V133.926' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M290.106 134.051V133.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M288.113 133.926H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M290.106 134.051V134.176' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M290.106 134.051V134.176' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M292.098 134.176H288.113' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M348.777 109.129V108.937' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M348.777 109.129V108.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M346.781 108.937H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M348.777 109.129V109.316' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M348.777 109.129V109.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M350.769 109.316H346.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M407.445 123.469V122.465' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M407.445 123.469V122.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M405.453 122.465H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M407.445 123.469V124.469' fill='#4747a4'/>
+<path clip-path='url(#clip3)' d='M407.445 123.469V124.469' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M409.437 124.469H405.453' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M117.711 203.937H120.949V139.062H117.711ZM176.379 203.937H179.617V133.176H176.379ZM235.051 203.937H238.285V140.941H235.051ZM293.719 203.937H296.957V131.734H293.719ZM352.387 203.937H355.625V133.238H352.387ZM411.055 203.937H414.293V124.781H411.055Z' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M117.711 203.937H120.949V139.062H117.711ZM176.379 203.937H179.617V133.176H176.379ZM235.051 203.937H238.285V140.941H235.051ZM293.719 203.937H296.957V131.734H293.719ZM352.387 203.937H355.625V133.238H352.387ZM411.055 203.937H414.293V124.781H411.055Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M119.328 139.062V138.871' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M119.328 139.062V138.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M117.336 138.871H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M119.328 139.062V139.25' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M119.328 139.062V139.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M121.325 139.25H117.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M178 133.176V133.176' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M176.008 133.176H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M178 133.176V133.176' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M176.008 133.176H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M236.668 140.941V140.5' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M236.668 140.941V140.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M234.676 140.5H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M236.668 140.941V141.379' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M236.668 140.941V141.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M238.66 141.379H234.675' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M295.336 131.734V131.672' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M295.336 131.734V131.672' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M293.344 131.672H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M295.336 131.734V131.797' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M295.336 131.734V131.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M297.328 131.797H293.343' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M354.008 133.238V133.176' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M354.008 133.238V133.176' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M352.012 133.175H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M354.008 133.238V133.301' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M354.008 133.238V133.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M355.999 133.301H352.015' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M412.676 124.781V124.719' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M412.676 124.781V124.719' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M410.684 124.719H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M412.676 124.781V124.844' fill='#292994'/>
+<path clip-path='url(#clip3)' d='M412.676 124.781V124.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M414.667 124.843H410.683' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M122.941 203.937H126.18V127.601H122.941ZM181.609 203.937H184.848V131.797H181.609ZM240.281 203.937H243.516V141.316H240.281ZM298.949 203.937H302.188V140H298.949ZM357.617 203.937H360.856V109.691H357.617ZM416.285 203.937H419.524V105.308H416.285Z' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M122.941 203.937H126.18V127.601H122.941ZM181.609 203.937H184.848V131.797H181.609ZM240.281 203.937H243.516V141.316H240.281ZM298.949 203.937H302.188V140H298.949ZM357.617 203.937H360.856V109.691H357.617ZM416.285 203.937H419.524V105.308H416.285Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M124.559 127.601V127.351' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M124.559 127.601V127.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M122.566 127.351H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M124.559 127.601V127.851' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M124.559 127.601V127.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M126.555 127.851H122.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M183.231 131.797V129.418' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M183.231 131.797V129.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M181.238 129.418H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M183.231 131.797V134.176' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M183.231 131.797V134.176' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M185.223 134.176H181.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M241.899 141.316V141.129' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M241.899 141.316V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M239.906 141.128H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M241.899 141.316V141.504' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M241.899 141.316V141.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M243.891 141.504H239.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M300.567 140V139.875' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M300.567 140V139.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M298.574 139.875H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M300.567 140V140.125' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M300.567 140V140.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M302.559 140.125H298.574' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M359.238 109.691V108.812' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M359.238 109.691V108.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M357.242 108.813H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M359.238 109.691V110.566' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M359.238 109.691V110.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M361.23 110.566H357.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M417.906 105.308V104.554' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M417.906 105.308V104.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M415.914 104.555H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M417.906 105.308V106.058' fill='#0a0a85'/>
+<path clip-path='url(#clip3)' d='M417.906 105.308V106.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M419.898 106.059H415.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M128.172 203.937H131.41V116.828H128.172ZM186.84 203.937H190.078V126.785H186.84ZM245.512 203.937H248.746V144.195H245.512ZM362.848 203.937H366.086V117.582H362.848ZM421.516 203.937H424.754V78.691H421.516Z' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M128.172 203.937H131.41V116.828H128.172ZM186.84 203.937H190.078V126.785H186.84ZM245.512 203.937H248.746V144.195H245.512ZM362.848 203.937H366.086V117.582H362.848ZM421.516 203.937H424.754V78.691H421.516Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M129.789 116.828V116.515' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M129.789 116.828V116.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M127.797 116.516H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M129.789 116.828V117.144' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M129.789 116.828V117.144' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M131.785 117.145H127.8' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M188.461 126.785V124.219' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M188.461 126.785V124.219' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M186.469 124.219H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M188.461 126.785V129.355' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M188.461 126.785V129.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M190.453 129.355H186.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M247.129 144.195V144.07' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M247.129 144.195V144.07' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M245.137 144.071H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M247.129 144.195V144.32' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M247.129 144.195V144.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M249.121 144.32H245.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M364.469 117.582V117.269' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M364.469 117.582V117.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M362.473 117.269H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M364.469 117.582V117.894' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M364.469 117.582V117.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M366.46 117.894H362.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M423.137 78.691V78.691' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M421.144 78.691H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M423.137 78.691V78.691' fill='#000076'/>
+<path clip-path='url(#clip3)' d='M421.144 78.691H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M133.402 203.937H136.641V140.5H133.402ZM192.07 203.937H195.309V138.621H192.07ZM250.742 203.937H253.977V140.875H250.742ZM309.41 203.937H312.649V140.625H309.41ZM368.078 203.937H371.317V141.066H368.078ZM426.746 203.937H429.984V142.629H426.746Z' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M133.402 203.937H136.641V140.5H133.402ZM192.07 203.937H195.309V138.621H192.07ZM250.742 203.937H253.977V140.875H250.742ZM309.41 203.937H312.649V140.625H309.41ZM368.078 203.937H371.317V141.066H368.078ZM426.746 203.937H429.984V142.629H426.746Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M135.02 140.5V140.187' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M135.02 140.5V140.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M133.027 140.187H137.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M135.02 140.5V140.812' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M135.02 140.5V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M137.016 140.812H133.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M193.692 138.621V138.621' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M191.699 138.621H195.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M193.692 138.621V138.621' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M191.699 138.621H195.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M252.359 140.875V140.5' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M252.359 140.875V140.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M250.367 140.5H254.352' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M252.359 140.875V141.254' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M252.359 140.875V141.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M254.352 141.254H250.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M311.027 140.625V140.375' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M311.027 140.625V140.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M309.035 140.375H313.02' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M311.027 140.625V140.875' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M311.027 140.625V140.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M313.02 140.875H309.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M369.699 141.066V140.812' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M369.699 141.066V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M367.703 140.812H371.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M369.699 141.066V141.316' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M369.699 141.066V141.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M371.692 141.316H367.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M428.367 142.629V140.062' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M428.367 142.629V140.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M426.375 140.063H430.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M428.367 142.629V145.199' fill='#000067'/>
+<path clip-path='url(#clip3)' d='M428.367 142.629V145.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip3)' d='M430.359 145.199H426.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -94.367 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.698 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 22.971 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 81.64 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.309 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 198.978 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -89.137 248.024)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.468 247.085)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.201 249.903)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.87 247.147)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.539 246.333)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.208 238.318)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.906 247.21)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.237 244.329)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.432 249.84)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.101 248.713)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.77 239.382)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.439 223.977)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.676 238.756)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -20.007 241.637)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 38.662 249.527)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.331 247.774)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 156 245.143)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 214.669 205.253)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -73.445 247.085)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.776 246.145)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 43.893 249.715)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 102.562 240.321)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.231 241.449)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 219.9 233.308)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -68.215 244.642)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.546 241.637)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.123 249.402)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 107.792 242.513)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.461 217.589)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.13 231.93)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.984 247.523)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -4.315 241.637)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.354 249.402)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.023 240.196)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 171.692 241.699)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.361 233.245)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.754 236.063)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.915 240.259)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.584 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.253 248.462)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.922 218.153)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.591 213.769)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.524 225.292)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.145 235.249)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.814 252.658)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.152 226.043)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.821 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-52' y='183.949'/>
+<use x='126.877' xlink:href='#g1-52' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -47.293 248.963)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 11.376 247.085)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 70.045 249.339)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.714 249.089)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 187.383 249.527)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 246.052 251.093)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -124.589 311.062)'>
+<use x='114.487' xlink:href='#g0-82' y='183.949'/>
+<use x='120.457' xlink:href='#g0-101' y='183.949'/>
+<use x='124.553' xlink:href='#g0-108' y='183.949'/>
+<use x='126.753' xlink:href='#g0-97' y='183.949'/>
+<use x='131.181' xlink:href='#g0-116' y='183.949'/>
+<use x='134.509' xlink:href='#g0-105' y='183.949'/>
+<use x='136.709' xlink:href='#g0-118' y='183.949'/>
+<use x='140.957' xlink:href='#g0-101' y='183.949'/>
+<use x='148.124' xlink:href='#g0-116' y='183.949'/>
+<use x='151.452' xlink:href='#g0-105' y='183.949'/>
+<use x='153.652' xlink:href='#g0-109' y='183.949'/>
+<use x='160.972' xlink:href='#g0-101' y='183.949'/>
+<use x='168.139' xlink:href='#g2-40' y='183.949'/>
+<use x='171.432' xlink:href='#g2-108' y='183.949'/>
+<use x='173.453' xlink:href='#g2-111' y='183.949'/>
+<use x='177.452' xlink:href='#g2-119' y='183.949'/>
+<use x='183' xlink:href='#g2-101' y='183.949'/>
+<use x='186.764' xlink:href='#g2-114' y='183.949'/>
+<use x='192.479' xlink:href='#g2-105' y='183.949'/>
+<use x='194.499' xlink:href='#g2-115' y='183.949'/>
+<use x='200.568' xlink:href='#g2-98' y='183.949'/>
+<use x='205.176' xlink:href='#g2-101' y='183.949'/>
+<use x='208.94' xlink:href='#g2-116' y='183.949'/>
+<use x='211.998' xlink:href='#g2-116' y='183.949'/>
+<use x='215.056' xlink:href='#g2-101' y='183.949'/>
+<use x='218.819' xlink:href='#g2-114' y='183.949'/>
+<use x='221.711' xlink:href='#g2-41' y='183.949'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-z4-2.svg b/extlib/mimalloc/doc/bench-2020/bench-z4-2.svg
new file mode 100644 (file)
index 0000000..9990cdc
--- /dev/null
@@ -0,0 +1,1146 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='243.704pt' version='1.1' viewBox='106.737 54.995 381.623 243.704' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip4'>
+<path d='M135.949 249.281H487.961V81.515H135.949Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-45' transform='scale(1.6)' xlink:href='#g1-45'/>
+<use id='g2-49' transform='scale(1.6)' xlink:href='#g1-49'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M3.248 -3.457H2.745V-1.963H0.986V-3.457H0.483V0H0.986V-1.634H2.745V0H3.248V-3.457Z' id='g1-72'/>
+<path d='M0.986 -3.457H0.483V0H0.986V-3.457Z' id='g1-73'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.611 -1.714C3.611 -2.745 2.854 -3.562 1.953 -3.562S0.294 -2.745 0.294 -1.714S1.061 0.105 1.953 0.105C2.849 0.105 3.611 -0.687 3.611 -1.714ZM1.953 -0.249C1.35 -0.249 0.797 -0.852 0.797 -1.793C0.797 -2.675 1.355 -3.218 1.953 -3.218S3.108 -2.675 3.108 -1.793C3.108 -0.847 2.555 -0.249 1.953 -0.249Z' id='g1-79'/>
+<path d='M1.868 -1.42C2.511 -1.42 3.083 -1.873 3.083 -2.446C3.083 -2.979 2.555 -3.457 1.833 -3.457H0.488V0H0.991V-1.42H1.868ZM1.709 -3.163C2.271 -3.163 2.63 -2.864 2.63 -2.446C2.63 -2.037 2.291 -1.729 1.709 -1.729H0.976V-3.163H1.709Z' id='g1-80'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M1.968 -1.823L3.228 -3.457H2.685L1.724 -2.182L0.742 -3.457H0.149L1.479 -1.823L0.075 0H0.618L1.724 -1.499L2.854 0H3.447L1.968 -1.823Z' id='g1-88'/>
+<path d='M2.934 -3.238V-3.457H0.369V-3.123H1.41C1.479 -3.123 1.539 -3.128 1.609 -3.128H2.291L0.294 -0.229V0H2.964V-0.354H2.466C1.958 -0.354 1.45 -0.344 0.941 -0.344L2.934 -3.238Z' id='g1-90'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g0-109'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page4'>
+<path d='M194.617 258.136V249.281M253.285 258.136V249.281M311.953 258.136V249.281M370.625 258.136V249.281M429.293 258.136V249.281M194.617 72.66V81.515M253.285 72.66V81.515M311.953 72.66V81.515M370.625 72.66V81.515M429.293 72.66V81.515' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 253.535V249.281M223.953 253.535V249.281M282.621 253.535V249.281M341.289 253.535V249.281M399.957 253.535V249.281M458.629 253.535V249.281M165.281 77.265V81.515M223.953 77.265V81.515M282.621 77.265V81.515M341.289 77.265V81.515M399.957 77.265V81.515M458.629 77.265V81.515' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281H140.199M135.949 215.73H140.199M135.949 182.176H140.199M135.949 148.625H140.199M135.949 115.07H140.199M135.949 81.515H140.199M487.961 249.281H483.711M487.961 215.73H483.711M487.961 182.176H483.711M487.961 148.625H483.711M487.961 115.07H483.711M487.961 81.515H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 249.281V81.515H487.961V249.281H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 61.588)'>
+<use x='168.285' xlink:href='#g2-97' y='201.694'/>
+<use x='172.353' xlink:href='#g2-108' y='201.694'/>
+<use x='174.373' xlink:href='#g2-108' y='201.694'/>
+<use x='176.393' xlink:href='#g2-111' y='201.694'/>
+<use x='180.863' xlink:href='#g2-99' y='201.694'/>
+<use x='184.627' xlink:href='#g2-45' y='201.694'/>
+<use x='187.449' xlink:href='#g2-116' y='201.694'/>
+<use x='190.507' xlink:href='#g2-101' y='201.694'/>
+<use x='194.271' xlink:href='#g2-115' y='201.694'/>
+<use x='197.517' xlink:href='#g2-116' y='201.694'/>
+<use x='200.575' xlink:href='#g2-49' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 61.588)'>
+<use x='168.285' xlink:href='#g2-97' y='201.694'/>
+<use x='172.353' xlink:href='#g2-108' y='201.694'/>
+<use x='174.373' xlink:href='#g2-108' y='201.694'/>
+<use x='176.393' xlink:href='#g2-111' y='201.694'/>
+<use x='180.863' xlink:href='#g2-99' y='201.694'/>
+<use x='184.627' xlink:href='#g2-45' y='201.694'/>
+<use x='187.449' xlink:href='#g2-116' y='201.694'/>
+<use x='190.507' xlink:href='#g2-101' y='201.694'/>
+<use x='194.271' xlink:href='#g2-115' y='201.694'/>
+<use x='197.517' xlink:href='#g2-116' y='201.694'/>
+<use x='200.575' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 61.588)'>
+<use x='168.285' xlink:href='#g2-115' y='201.694'/>
+<use x='171.531' xlink:href='#g2-104' y='201.694'/>
+<use x='175.904' xlink:href='#g2-54' y='201.694'/>
+<use x='180.138' xlink:href='#g2-98' y='201.694'/>
+<use x='184.746' xlink:href='#g2-101' y='201.694'/>
+<use x='188.509' xlink:href='#g2-110' y='201.694'/>
+<use x='192.882' xlink:href='#g2-99' y='201.694'/>
+<use x='196.646' xlink:href='#g2-104' y='201.694'/>
+<use x='201.018' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 61.588)'>
+<use x='168.285' xlink:href='#g2-115' y='201.694'/>
+<use x='171.531' xlink:href='#g2-104' y='201.694'/>
+<use x='175.904' xlink:href='#g2-56' y='201.694'/>
+<use x='180.138' xlink:href='#g2-98' y='201.694'/>
+<use x='184.746' xlink:href='#g2-101' y='201.694'/>
+<use x='188.509' xlink:href='#g2-110' y='201.694'/>
+<use x='192.882' xlink:href='#g2-99' y='201.694'/>
+<use x='196.646' xlink:href='#g2-104' y='201.694'/>
+<use x='201.018' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 61.588)'>
+<use x='168.285' xlink:href='#g2-120' y='201.694'/>
+<use x='172.187' xlink:href='#g2-109' y='201.694'/>
+<use x='178.912' xlink:href='#g2-97' y='201.694'/>
+<use x='182.98' xlink:href='#g2-108' y='201.694'/>
+<use x='185' xlink:href='#g2-108' y='201.694'/>
+<use x='187.02' xlink:href='#g2-111' y='201.694'/>
+<use x='191.49' xlink:href='#g2-99' y='201.694'/>
+<use x='195.254' xlink:href='#g2-45' y='201.694'/>
+<use x='198.076' xlink:href='#g2-116' y='201.694'/>
+<use x='201.134' xlink:href='#g2-101' y='201.694'/>
+<use x='204.898' xlink:href='#g2-115' y='201.694'/>
+<use x='208.144' xlink:href='#g2-116' y='201.694'/>
+<use x='211.202' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 61.588)'>
+<use x='168.285' xlink:href='#g2-99' y='201.694'/>
+<use x='172.049' xlink:href='#g2-97' y='201.694'/>
+<use x='176.117' xlink:href='#g2-99' y='201.694'/>
+<use x='179.88' xlink:href='#g2-104' y='201.694'/>
+<use x='184.253' xlink:href='#g2-101' y='201.694'/>
+<use x='188.017' xlink:href='#g2-45' y='201.694'/>
+<use x='190.839' xlink:href='#g2-115' y='201.694'/>
+<use x='194.086' xlink:href='#g2-99' y='201.694'/>
+<use x='197.849' xlink:href='#g2-114' y='201.694'/>
+<use x='200.741' xlink:href='#g2-97' y='201.694'/>
+<use x='204.81' xlink:href='#g2-116' y='201.694'/>
+<use x='207.868' xlink:href='#g2-99' y='201.694'/>
+<use x='211.631' xlink:href='#g2-104' y='201.694'/>
+<use x='216.004' xlink:href='#g2-78' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 49.223)'>
+<use x='168.285' xlink:href='#g1-48' y='201.694'/>
+<use x='170.931' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.67)'>
+<use x='168.285' xlink:href='#g1-48' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -17.883)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -51.436)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -84.989)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -118.543)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-53' y='201.694'/>
+<use x='175.048' xlink:href='#g1-120' y='201.694'/>
+</g>
+<path clip-path='url(#clip4)' d='M135.949 182.176H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M140.125 249.281H143.363V182.176H140.125ZM198.797 249.281H202.035V182.176H198.797ZM257.465 249.281H260.703V182.176H257.465ZM316.133 249.281H319.371V182.176H316.133ZM374.801 249.281H378.039V182.176H374.801ZM433.473 249.281H436.711V182.176H433.473Z' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M140.125 249.281H143.363V182.176H140.125ZM198.797 249.281H202.035V182.176H198.797ZM257.465 249.281H260.703V182.176H257.465ZM316.133 249.281H319.371V182.176H316.133ZM374.801 249.281H378.039V182.176H374.801ZM433.473 249.281H436.711V182.176H433.473Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M141.746 182.176V181.906' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M141.746 182.176V181.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M139.754 181.907H143.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M141.746 182.176V182.445' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M141.746 182.176V182.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M143.739 182.446H139.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M200.414 182.176V181.773' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M200.414 182.176V181.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M198.422 181.774H202.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M200.414 182.176V182.578' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M200.414 182.176V182.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M202.406 182.578H198.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M259.082 182.176V180.297' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M259.082 182.176V180.297' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M257.09 180.297H261.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M259.082 182.176V184.054' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M259.082 182.176V184.054' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M261.074 184.055H257.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M317.754 182.176V181.57' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M317.754 182.176V181.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M315.762 181.57H319.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M317.754 182.176V182.781' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M317.754 182.176V182.781' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M319.746 182.781H315.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M376.422 182.176V181.035' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M376.422 182.176V181.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M374.43 181.035H378.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M376.422 182.176V183.316' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M376.422 182.176V183.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M378.414 183.316H374.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M435.09 182.176V179.156' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M435.09 182.176V179.156' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M433.098 179.156H437.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M435.09 182.176V185.195' fill='#e0e0f0'/>
+<path clip-path='url(#clip4)' d='M435.09 182.176V185.195' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M437.082 185.195H433.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M145.356 249.281H148.594V181.371H145.356ZM204.028 249.281H207.266V179.492H204.028ZM262.695 249.281H265.934V149.898H262.695ZM321.363 249.281H324.602V81.515H321.363ZM380.031 249.281H383.27V81.515H380.031ZM438.703 249.281H441.942V81.515H438.703Z' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M145.356 249.281H148.594V181.371H145.356ZM204.028 249.281H207.266V179.492H204.028ZM262.695 249.281H265.934V149.898H262.695ZM321.363 249.281H324.602V81.515H321.363ZM380.031 249.281H383.27V81.515H380.031ZM438.703 249.281H441.942V81.515H438.703Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M146.977 181.371V181.238' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M146.977 181.371V181.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M144.984 181.239H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M146.977 181.371V181.504' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M146.977 181.371V181.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M148.969 181.504H144.984' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M205.645 179.492V179.359' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M205.645 179.492V179.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M203.652 179.36H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M205.645 179.492V179.625' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M205.645 179.492V179.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M207.636 179.625H203.652' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M264.313 149.898V149.359' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M264.313 149.898V149.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M262.32 149.359H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M264.313 149.898V150.433' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M264.313 149.898V150.433' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M266.304 150.434H262.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M322.984 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M320.992 81.516H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M322.984 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M320.992 81.516H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M381.652 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M379.66 81.516H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M381.652 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M379.66 81.516H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M440.32 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M438.328 81.516H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M440.32 81.515V81.515' fill='#c2c2e1'/>
+<path clip-path='url(#clip4)' d='M438.328 81.516H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M150.586 249.281H153.824V178.687H150.586ZM209.258 249.281H212.496V177.679H209.258ZM267.926 249.281H271.164V81.515H267.926ZM326.594 249.281H329.832V133.39H326.594ZM385.262 249.281H388.5V110.91H385.262ZM443.934 249.281H447.172V81.515H443.934Z' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M150.586 249.281H153.824V178.687H150.586ZM209.258 249.281H212.496V177.679H209.258ZM267.926 249.281H271.164V81.515H267.926ZM326.594 249.281H329.832V133.39H326.594ZM385.262 249.281H388.5V110.91H385.262ZM443.934 249.281H447.172V81.515H443.934Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M152.207 178.687V178.418' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M152.207 178.687V178.418' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M150.215 178.418H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M152.207 178.687V178.953' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M152.207 178.687V178.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M154.2 178.953H150.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M210.875 177.679V177.547' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M210.875 177.679V177.547' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M208.883 177.547H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M210.875 177.679V177.812' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M210.875 177.679V177.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M212.867 177.812H208.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M269.543 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M267.551 81.516H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M269.543 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M267.551 81.516H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M328.215 133.39V131.176' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M328.215 133.39V131.176' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M326.223 131.176H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M328.215 133.39V135.605' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M328.215 133.39V135.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M330.207 135.606H326.219' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M386.883 110.91V110.371' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M386.883 110.91V110.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M384.891 110.371H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M386.883 110.91V111.445' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M386.883 110.91V111.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M388.875 111.445H384.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M445.551 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M443.559 81.516H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M445.551 81.515V81.515' fill='#a3a3d1'/>
+<path clip-path='url(#clip4)' d='M443.559 81.516H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M155.817 249.281H159.055V161.91H155.817ZM214.488 249.281H217.727V158.219H214.488ZM273.156 249.281H276.395V81.515H273.156ZM331.824 249.281H335.063V150.097H331.824ZM390.492 249.281H393.731V162.445H390.492ZM449.164 249.281H452.402V181.101H449.164Z' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M155.817 249.281H159.055V161.91H155.817ZM214.488 249.281H217.727V158.219H214.488ZM273.156 249.281H276.395V81.515H273.156ZM331.824 249.281H335.063V150.097H331.824ZM390.492 249.281H393.731V162.445H390.492ZM449.164 249.281H452.402V181.101H449.164Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M157.438 161.91V161.777' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M157.438 161.91V161.777' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M155.445 161.777H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M157.438 161.91V162.043' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M157.438 161.91V162.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M159.43 162.043H155.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M216.106 158.219V158.019' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M216.106 158.219V158.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M214.113 158.02H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M216.106 158.219V158.422' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M216.106 158.219V158.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M218.098 158.422H214.113' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M274.774 81.515V81.515' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M272.781 81.516H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M274.774 81.515V81.515' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M272.781 81.516H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M333.445 150.097V149.496' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M333.445 150.097V149.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M331.453 149.496H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M333.445 150.097V150.703' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M333.445 150.097V150.703' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M335.437 150.703H331.449' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M392.113 162.445V162.179' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M392.113 162.445V162.179' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M390.121 162.18H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M392.113 162.445V162.715' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M392.113 162.445V162.715' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M394.105 162.714H390.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M450.781 181.101V177.41' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M450.781 181.101V177.41' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M448.789 177.411H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M450.781 181.101V184.793' fill='#8585c2'/>
+<path clip-path='url(#clip4)' d='M450.781 181.101V184.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M452.773 184.793H448.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M161.047 249.281H164.285V169.023H161.047ZM219.719 249.281H222.957V168.152H219.719ZM278.387 249.281H281.625V81.515H278.387ZM337.055 249.281H340.293V81.515H337.055ZM395.723 249.281H398.961V81.515H395.723ZM454.395 249.281H457.633V81.515H454.395Z' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M161.047 249.281H164.285V169.023H161.047ZM219.719 249.281H222.957V168.152H219.719ZM278.387 249.281H281.625V81.515H278.387ZM337.055 249.281H340.293V81.515H337.055ZM395.723 249.281H398.961V81.515H395.723ZM454.395 249.281H457.633V81.515H454.395Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M162.668 169.023V168.957' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M162.668 169.023V168.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M160.676 168.957H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M162.668 169.023V169.09' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M162.668 169.023V169.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M164.661 169.089H160.676' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M221.336 168.152V168.015' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M221.336 168.152V168.015' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M219.344 168.016H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M221.336 168.152V168.285' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M221.336 168.152V168.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M223.329 168.285H219.344' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M280.004 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M278.012 81.516H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M280.004 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M278.012 81.516H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M338.676 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M336.684 81.516H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M338.676 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M336.684 81.516H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M397.344 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M395.352 81.516H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M397.344 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M395.352 81.516H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M456.012 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M454.02 81.516H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M456.012 81.515V81.515' fill='#6666b3'/>
+<path clip-path='url(#clip4)' d='M454.02 81.516H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M166.278 249.281H169.516V175.734H166.278ZM224.949 249.281H228.188V169.023H224.949ZM283.617 249.281H286.856V107.488H283.617ZM342.285 249.281H345.524V81.515H342.285ZM400.953 249.281H404.192V81.515H400.953ZM459.625 249.281H462.863V81.515H459.625Z' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M166.278 249.281H169.516V175.734H166.278ZM224.949 249.281H228.188V169.023H224.949ZM283.617 249.281H286.856V107.488H283.617ZM342.285 249.281H345.524V81.515H342.285ZM400.953 249.281H404.192V81.515H400.953ZM459.625 249.281H462.863V81.515H459.625Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M167.899 175.734V175.465' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M167.899 175.734V175.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M165.906 175.465H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M167.899 175.734V176.004' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M167.899 175.734V176.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M169.891 176.004H165.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M226.567 169.023V168.554' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M226.567 169.023V168.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M224.574 168.555H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M226.567 169.023V169.492' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M226.567 169.023V169.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M228.559 169.492H224.574' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M285.234 107.488V107.015' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M285.234 107.488V107.015' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M283.242 107.015H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M285.234 107.488V107.957' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M285.234 107.488V107.957' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M287.227 107.957H283.242' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M343.906 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M341.914 81.516H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M343.906 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M341.914 81.516H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M402.574 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M400.582 81.516H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M402.574 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M400.582 81.516H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M461.242 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M459.25 81.516H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M461.242 81.515V81.515' fill='#4747a4'/>
+<path clip-path='url(#clip4)' d='M459.25 81.516H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M171.508 249.281H174.746V168.82H171.508ZM230.18 249.281H233.414V168.621H230.18ZM288.848 249.281H292.086V81.515H288.848ZM347.516 249.281H350.754V81.515H347.516ZM406.184 249.281H409.422V81.515H406.184ZM464.856 249.281H468.094V81.515H464.856Z' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M171.508 249.281H174.746V168.82H171.508ZM230.18 249.281H233.414V168.621H230.18ZM288.848 249.281H292.086V81.515H288.848ZM347.516 249.281H350.754V81.515H347.516ZM406.184 249.281H409.422V81.515H406.184ZM464.856 249.281H468.094V81.515H464.856Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M173.129 168.82V168.554' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M173.129 168.82V168.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M171.137 168.555H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M173.129 168.82V169.09' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M173.129 168.82V169.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M175.122 169.089H171.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M231.797 168.621V168.554' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M231.797 168.621V168.554' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M229.805 168.555H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M231.797 168.621V168.687' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M231.797 168.621V168.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M233.79 168.688H229.805' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M290.465 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M288.473 81.516H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M290.465 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M288.473 81.516H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M349.137 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M347.145 81.516H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M349.137 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M347.145 81.516H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M407.805 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M405.813 81.516H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M407.805 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M405.813 81.516H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M466.473 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M464.481 81.516H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M466.473 81.515V81.515' fill='#292994'/>
+<path clip-path='url(#clip4)' d='M464.481 81.516H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M411.414 249.281H414.652V133.59H411.414ZM176.738 249.281H179.977V162.113H176.738ZM235.41 249.281H238.645V162.648H235.41ZM294.078 249.281H297.317V81.515H294.078ZM352.746 249.281H355.984V125.875H352.746ZM470.086 249.281H473.324V181.035H470.086Z' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M411.414 249.281H414.652V133.59H411.414ZM176.738 249.281H179.977V162.113H176.738ZM235.41 249.281H238.645V162.648H235.41ZM294.078 249.281H297.317V81.515H294.078ZM352.746 249.281H355.984V125.875H352.746ZM470.086 249.281H473.324V181.035H470.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M413.035 133.59V126.211' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M413.035 133.59V126.211' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M411.043 126.211H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M413.035 133.59V140.972' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M413.035 133.59V140.972' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M415.027 140.973H411.043' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M178.36 162.113V161.777' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M178.36 162.113V161.777' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M176.367 161.777H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M178.36 162.113V162.445' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M178.36 162.113V162.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M180.352 162.445H176.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M237.027 162.648V162.515' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M237.027 162.648V162.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M235.035 162.516H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M237.027 162.648V162.781' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M237.027 162.648V162.781' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M239.02 162.781H235.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M295.695 81.515V81.515' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M293.703 81.516H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M295.695 81.515V81.515' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M293.703 81.516H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M354.367 125.875V125.672' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M354.367 125.875V125.672' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M352.375 125.672H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M354.367 125.875V126.074' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M354.367 125.875V126.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M356.359 126.074H352.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M471.703 181.035V178.219' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M471.703 181.035V178.219' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M469.711 178.219H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M471.703 181.035V183.855' fill='#0a0a85'/>
+<path clip-path='url(#clip4)' d='M471.703 181.035V183.855' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M473.695 183.856H469.711' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M181.969 249.281H185.207V154.594H181.969ZM240.641 249.281H243.875V149.695H240.641ZM299.309 249.281H302.547V81.515H299.309ZM357.977 249.281H361.215V81.515H357.977ZM475.317 249.281H478.555V81.515H475.317Z' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M181.969 249.281H185.207V154.594H181.969ZM240.641 249.281H243.875V149.695H240.641ZM299.309 249.281H302.547V81.515H299.309ZM357.977 249.281H361.215V81.515H357.977ZM475.317 249.281H478.555V81.515H475.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M183.59 154.594V154.461' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M183.59 154.594V154.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M181.598 154.461H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M183.59 154.594V154.73' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M183.59 154.594V154.73' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M185.582 154.731H181.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M242.258 149.695V149.562' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M242.258 149.695V149.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M240.266 149.563H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M242.258 149.695V149.832' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M242.258 149.695V149.832' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M244.25 149.832H240.265' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M300.926 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M298.933 81.516H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M300.926 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M298.933 81.516H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M359.598 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M357.606 81.516H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M359.598 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M357.606 81.516H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M476.934 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M474.942 81.516H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M476.934 81.515V81.515' fill='#000076'/>
+<path clip-path='url(#clip4)' d='M474.942 81.516H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M187.199 249.281H190.438V181.64H187.199ZM245.871 249.281H249.106V181.64H245.871ZM304.539 249.281H307.777V164.258H304.539ZM363.207 249.281H366.445V151.105H363.207ZM421.875 249.281H425.113V179.828H421.875ZM480.547 249.281H483.785V181.371H480.547Z' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M187.199 249.281H190.438V181.64H187.199ZM245.871 249.281H249.106V181.64H245.871ZM304.539 249.281H307.777V164.258H304.539ZM363.207 249.281H366.445V151.105H363.207ZM421.875 249.281H425.113V179.828H421.875ZM480.547 249.281H483.785V181.371H480.547Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M188.82 181.64V181.57' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M188.82 181.64V181.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M186.828 181.57H190.813' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M188.82 181.64V181.707' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M188.82 181.64V181.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M190.813 181.707H186.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M247.488 181.64V181.437' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M247.488 181.64V181.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M245.496 181.437H249.481' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M247.488 181.64V181.84' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M247.488 181.64V181.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M249.481 181.84H245.496' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M306.156 164.258V163.992' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M306.156 164.258V163.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M304.164 163.992H308.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M306.156 164.258V164.527' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M306.156 164.258V164.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M308.149 164.527H304.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M364.828 151.105V150.168' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M364.828 151.105V150.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M362.836 150.168H366.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M364.828 151.105V152.047' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M364.828 151.105V152.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M366.82 152.047H362.832' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M423.496 179.828V179.09' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M423.496 179.828V179.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M421.504 179.09H425.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M423.496 179.828V180.566' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M423.496 179.828V180.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M425.488 180.567H421.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M482.164 181.371V178.148' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M482.164 181.371V178.148' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M480.172 178.149H484.156' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M482.164 181.371V184.594' fill='#000067'/>
+<path clip-path='url(#clip4)' d='M482.164 181.371V184.594' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M484.156 184.594H480.172' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip4)' d='M419.477 298.301H487.762V276.324H419.477Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 254.512 92.648)'>
+<use x='168.285' xlink:href='#g1-72' y='190.457'/>
+<use x='172.021' xlink:href='#g1-80' y='190.457'/>
+<use x='175.402' xlink:href='#g1-45' y='190.457'/>
+<use x='177.167' xlink:href='#g1-90' y='190.457'/>
+<use x='180.401' xlink:href='#g1-52' y='190.457'/>
+<use x='183.047' xlink:href='#g1-45' y='190.457'/>
+<use x='184.812' xlink:href='#g1-71' y='190.457'/>
+<use x='188.34' xlink:href='#g1-52' y='190.457'/>
+<use x='190.987' xlink:href='#g1-44' y='190.457'/>
+<use x='194.221' xlink:href='#g1-49' y='190.457'/>
+<use x='196.867' xlink:href='#g1-54' y='190.457'/>
+<use x='199.514' xlink:href='#g1-71' y='190.457'/>
+<use x='203.042' xlink:href='#g1-98' y='190.457'/>
+<use x='168.285' xlink:href='#g1-56' y='196.075'/>
+<use x='170.931' xlink:href='#g1-45' y='196.075'/>
+<use x='172.695' xlink:href='#g1-99' y='196.075'/>
+<use x='175.048' xlink:href='#g1-111' y='196.075'/>
+<use x='177.547' xlink:href='#g1-114' y='196.075'/>
+<use x='179.355' xlink:href='#g1-101' y='196.075'/>
+<use x='183.471' xlink:href='#g1-73' y='196.075'/>
+<use x='184.941' xlink:href='#g1-110' y='196.075'/>
+<use x='187.674' xlink:href='#g1-116' y='196.075'/>
+<use x='189.585' xlink:href='#g1-101' y='196.075'/>
+<use x='191.938' xlink:href='#g1-108' y='196.075'/>
+<use x='194.965' xlink:href='#g1-88' y='196.075'/>
+<use x='198.493' xlink:href='#g1-69' y='196.075'/>
+<use x='201.667' xlink:href='#g1-79' y='196.075'/>
+<use x='205.576' xlink:href='#g1-78' y='196.075'/>
+<use x='211.076' xlink:href='#g1-64' y='196.075'/>
+<use x='214.605' xlink:href='#g1-50' y='196.075'/>
+<use x='217.251' xlink:href='#g1-46' y='196.075'/>
+<use x='218.721' xlink:href='#g1-55' y='196.075'/>
+<use x='221.368' xlink:href='#g1-71' y='196.075'/>
+<use x='224.896' xlink:href='#g1-104' y='196.075'/>
+<use x='227.629' xlink:href='#g1-122' y='196.075'/>
+<use x='168.285' xlink:href='#g1-85' y='201.694'/>
+<use x='171.917' xlink:href='#g1-98' y='201.694'/>
+<use x='174.65' xlink:href='#g1-117' y='201.694'/>
+<use x='177.383' xlink:href='#g1-110' y='201.694'/>
+<use x='180.116' xlink:href='#g1-116' y='201.694'/>
+<use x='182.027' xlink:href='#g1-117' y='201.694'/>
+<use x='186.524' xlink:href='#g1-49' y='201.694'/>
+<use x='189.17' xlink:href='#g1-56' y='201.694'/>
+<use x='191.817' xlink:href='#g1-46' y='201.694'/>
+<use x='193.287' xlink:href='#g1-48' y='201.694'/>
+<use x='195.933' xlink:href='#g1-52' y='201.694'/>
+<use x='198.58' xlink:href='#g1-46' y='201.694'/>
+<use x='200.05' xlink:href='#g1-49' y='201.694'/>
+<use x='202.696' xlink:href='#g1-44' y='201.694'/>
+<use x='205.931' xlink:href='#g1-71' y='201.694'/>
+<use x='209.459' xlink:href='#g1-67' y='201.694'/>
+<use x='212.841' xlink:href='#g1-67' y='201.694'/>
+<use x='217.986' xlink:href='#g1-55' y='201.694'/>
+<use x='220.633' xlink:href='#g1-46' y='201.694'/>
+<use x='222.103' xlink:href='#g1-52' y='201.694'/>
+<use x='224.749' xlink:href='#g1-46' y='201.694'/>
+<use x='226.219' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -58.314 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.355 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.024 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 117.693 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.362 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.031 344.257)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -53.084 343.452)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 5.585 341.573)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.254 311.979)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-56' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 122.923 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-54' y='201.694'/>
+<use x='180.675' xlink:href='#g1-53' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 181.592 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-53' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-48' y='201.694'/>
+<use x='180.675' xlink:href='#g1-54' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.261 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-49' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-51' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -47.853 340.768)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-53' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 10.816 339.761)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-55' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 69.485 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-51' y='201.694'/>
+<use x='180.675' xlink:href='#g1-54' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.154 295.471)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-51' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 186.823 272.99)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 245.492 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-50' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-48' y='201.694'/>
+<use x='183.321' xlink:href='#g1-55' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -42.623 323.991)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 16.046 320.3)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.715 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-56' y='201.694'/>
+<use x='180.675' xlink:href='#g1-57' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.384 312.18)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-56' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 192.053 324.528)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-57' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 250.722 343.183)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-50' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -37.392 331.104)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.277 330.232)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.946 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-54' y='201.694'/>
+<use x='180.675' xlink:href='#g1-53' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.615 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-53' y='201.694'/>
+<use x='180.675' xlink:href='#g1-49' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.284 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-53' y='201.694'/>
+<use x='180.675' xlink:href='#g1-49' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 255.953 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-54' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-49' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.162 337.815)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.507 331.104)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.176 269.568)'>
+<use x='168.285' xlink:href='#g1-50' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-49' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.845 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-48' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-50' y='201.694'/>
+<use x='183.321' xlink:href='#g1-50' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.514 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-49' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-52' y='201.694'/>
+<use x='183.321' xlink:href='#g1-50' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.183 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-55' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-48' y='201.694'/>
+<use x='180.675' xlink:href='#g1-49' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -26.931 330.903)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.738 330.702)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.407 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-50' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-54' y='201.694'/>
+<use x='180.675' xlink:href='#g1-55' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 149.076 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-54' y='201.694'/>
+<use x='180.675' xlink:href='#g1-48' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.745 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-53' y='201.694'/>
+<use x='180.675' xlink:href='#g1-49' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 266.414 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-53' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-55' y='201.694'/>
+<use x='180.675' xlink:href='#g1-54' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.975 295.672)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-55' y='201.694'/>
+<use x='175.048' xlink:href='#g1-50' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -21.701 324.192)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-51' y='201.694'/>
+<use x='175.048' xlink:href='#g1-48' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.968 324.729)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-57' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.637 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-51' y='201.694'/>
+<use x='180.675' xlink:href='#g1-55' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 154.306 287.955)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-56' y='201.694'/>
+<use x='175.048' xlink:href='#g1-52' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 271.644 343.116)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-50' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.471 316.676)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 42.198 311.778)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-56' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.867 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-54' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-48' y='201.694'/>
+<use x='180.675' xlink:href='#g1-54' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.536 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-51' y='201.694'/>
+<use x='176.558' xlink:href='#g1-46' y='201.694'/>
+<use x='178.029' xlink:href='#g1-49' y='201.694'/>
+<use x='180.675' xlink:href='#g1-52' y='201.694'/>
+<use x='183.321' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 276.874 243.598)'>
+<use x='163.396' xlink:href='#g3-1' y='201.694'/>
+<use x='166.901' xlink:href='#g3-1' y='201.694'/>
+<use x='170.407' xlink:href='#g3-1' y='201.694'/>
+<use x='173.912' xlink:href='#g1-49' y='201.694'/>
+<use x='176.558' xlink:href='#g1-49' y='201.694'/>
+<use x='179.205' xlink:href='#g1-46' y='201.694'/>
+<use x='180.675' xlink:href='#g1-56' y='201.694'/>
+<use x='183.321' xlink:href='#g1-56' y='201.694'/>
+<use x='185.968' xlink:href='#g1-120' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -11.24 343.72)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 47.429 343.72)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 106.098 326.34)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-50' y='201.694'/>
+<use x='175.048' xlink:href='#g1-55' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 164.767 313.187)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-52' y='201.694'/>
+<use x='175.048' xlink:href='#g1-54' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 223.436 341.908)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-51' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 282.105 343.452)'>
+<use x='168.285' xlink:href='#g1-49' y='201.694'/>
+<use x='170.931' xlink:href='#g1-46' y='201.694'/>
+<use x='172.401' xlink:href='#g1-48' y='201.694'/>
+<use x='175.048' xlink:href='#g1-49' y='201.694'/>
+</g>
+<g transform='matrix(0 -1 1 0 -88.536 388.944)'>
+<use x='168.285' xlink:href='#g0-82' y='201.694'/>
+<use x='174.255' xlink:href='#g0-101' y='201.694'/>
+<use x='178.351' xlink:href='#g0-108' y='201.694'/>
+<use x='180.551' xlink:href='#g0-97' y='201.694'/>
+<use x='184.979' xlink:href='#g0-116' y='201.694'/>
+<use x='188.307' xlink:href='#g0-105' y='201.694'/>
+<use x='190.507' xlink:href='#g0-118' y='201.694'/>
+<use x='194.755' xlink:href='#g0-101' y='201.694'/>
+<use x='201.922' xlink:href='#g0-116' y='201.694'/>
+<use x='205.25' xlink:href='#g0-105' y='201.694'/>
+<use x='207.45' xlink:href='#g0-109' y='201.694'/>
+<use x='214.77' xlink:href='#g0-101' y='201.694'/>
+<use x='221.937' xlink:href='#g2-40' y='201.694'/>
+<use x='225.231' xlink:href='#g2-108' y='201.694'/>
+<use x='227.251' xlink:href='#g2-111' y='201.694'/>
+<use x='231.25' xlink:href='#g2-119' y='201.694'/>
+<use x='236.799' xlink:href='#g2-101' y='201.694'/>
+<use x='240.562' xlink:href='#g2-114' y='201.694'/>
+<use x='246.277' xlink:href='#g2-105' y='201.694'/>
+<use x='248.297' xlink:href='#g2-115' y='201.694'/>
+<use x='254.366' xlink:href='#g2-98' y='201.694'/>
+<use x='258.974' xlink:href='#g2-101' y='201.694'/>
+<use x='262.738' xlink:href='#g2-116' y='201.694'/>
+<use x='265.796' xlink:href='#g2-116' y='201.694'/>
+<use x='268.854' xlink:href='#g2-101' y='201.694'/>
+<use x='272.618' xlink:href='#g2-114' y='201.694'/>
+<use x='275.51' xlink:href='#g2-41' y='201.694'/>
+</g>
+<path d='M136.149 296.672H402.137V279.679H136.149Z' fill='#ffffff'/>
+<path d='M136.149 296.672H402.137V279.679H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='#e0e0f0'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 88.465)'>
+<use x='185.011' xlink:href='#g2-109' y='201.694'/>
+<use x='191.736' xlink:href='#g2-105' y='201.694'/>
+</g>
+<path d='M163.422 290.168H166.41V282.199H163.422ZM169.398 290.168H172.391V284.191H169.398Z' fill='#c2c2e1'/>
+<path d='M163.422 290.168H166.41V282.199H163.422ZM169.398 290.168H172.391V284.191H169.398Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 88.011)'>
+<use x='208.137' xlink:href='#g2-116' y='201.694'/>
+<use x='211.195' xlink:href='#g2-99' y='201.694'/>
+</g>
+<path d='M185.586 290.168H188.574V282.199H185.586ZM191.563 290.168H194.555V284.191H191.563Z' fill='#a3a3d1'/>
+<path d='M185.586 290.168H188.574V282.199H185.586ZM191.563 290.168H194.555V284.191H191.563Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 88.465)'>
+<use x='229.9' xlink:href='#g2-106' y='201.694'/>
+<use x='232.155' xlink:href='#g2-101' y='201.694'/>
+</g>
+<path d='M206.949 290.168H209.938V282.199H206.949ZM212.926 290.168H215.914V284.191H212.926Z' fill='#8585c2'/>
+<path d='M206.949 290.168H209.938V282.199H206.949ZM212.926 290.168H215.914V284.191H212.926Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 87.505)'>
+<use x='252.061' xlink:href='#g2-115' y='201.694'/>
+<use x='255.307' xlink:href='#g2-110' y='201.694'/>
+</g>
+<path d='M229.91 290.168H232.898V282.199H229.91ZM235.887 290.168H238.875V284.191H235.887Z' fill='#6666b3'/>
+<path d='M229.91 290.168H232.898V282.199H229.91ZM235.887 290.168H238.875V284.191H235.887Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 87.505)'>
+<use x='274.845' xlink:href='#g2-114' y='201.694'/>
+<use x='277.737' xlink:href='#g2-112' y='201.694'/>
+</g>
+<path d='M252.516 290.168H255.504V282.199H252.516ZM258.496 290.168H261.484V284.191H258.496Z' fill='#4747a4'/>
+<path d='M252.516 290.168H255.504V282.199H252.516ZM258.496 290.168H261.484V284.191H258.496Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 88.501)'>
+<use x='303.672' xlink:href='#g2-104' y='201.694'/>
+<use x='308.045' xlink:href='#g2-111' y='201.694'/>
+<use x='312.279' xlink:href='#g2-97' y='201.694'/>
+<use x='316.112' xlink:href='#g2-114' y='201.694'/>
+<use x='319.004' xlink:href='#g2-100' y='201.694'/>
+</g>
+<path d='M287.563 290.168H290.551V282.199H287.563ZM293.543 290.168H296.531V284.191H293.543Z' fill='#292994'/>
+<path d='M287.563 290.168H290.551V282.199H287.563ZM293.543 290.168H296.531V284.191H293.543Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 88.501)'>
+<use x='337.19' xlink:href='#g2-103' y='201.694'/>
+<use x='341.424' xlink:href='#g2-108' y='201.694'/>
+<use x='343.444' xlink:href='#g2-105' y='201.694'/>
+<use x='345.464' xlink:href='#g2-98' y='201.694'/>
+<use x='350.072' xlink:href='#g2-99' y='201.694'/>
+</g>
+<path d='M319.551 290.168H322.539V282.199H319.551ZM325.527 290.168H328.52V284.191H325.527Z' fill='#0a0a85'/>
+<path d='M319.551 290.168H322.539V282.199H319.551ZM325.527 290.168H328.52V284.191H325.527Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 88.501)'>
+<use x='366.757' xlink:href='#g2-116' y='201.694'/>
+<use x='369.815' xlink:href='#g2-98' y='201.694'/>
+<use x='374.187' xlink:href='#g2-98' y='201.694'/>
+</g>
+<path d='M346.699 290.168H349.688V282.199H346.699ZM352.676 290.168H355.664V284.191H352.676Z' fill='#000076'/>
+<path d='M346.699 290.168H349.688V282.199H346.699ZM352.676 290.168H355.664V284.191H352.676Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -34.135 87.505)'>
+<use x='392.986' xlink:href='#g2-115' y='201.694'/>
+<use x='396.233' xlink:href='#g2-109' y='201.694'/>
+</g>
+<path d='M372.012 290.168H375V282.199H372.012ZM377.988 290.168H380.977V284.191H377.988Z' fill='#000067'/>
+<path d='M372.012 290.168H375V282.199H372.012ZM377.988 290.168H380.977V284.191H377.988Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.145 88.465)'>
+<use x='419.31' xlink:href='#g2-115' y='201.694'/>
+<use x='422.556' xlink:href='#g2-109' y='201.694'/>
+<use x='429.281' xlink:href='#g2-105' y='201.694'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-z4-rss-1.svg b/extlib/mimalloc/doc/bench-2020/bench-z4-rss-1.svg
new file mode 100644 (file)
index 0000000..891f7d6
--- /dev/null
@@ -0,0 +1,796 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='164.687pt' version='1.1' viewBox='52.938 54.996 381.625 164.687' width='381.625pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip9'>
+<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-102' transform='scale(1.6)' xlink:href='#g1-102'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M0.946 -1.898H1.514V-2.212H0.932V-2.785C0.932 -3.128 1.245 -3.178 1.41 -3.178C1.514 -3.178 1.649 -3.163 1.833 -3.093V-3.457C1.704 -3.487 1.549 -3.507 1.415 -3.507C0.902 -3.507 0.528 -3.138 0.528 -2.645V-2.212H0.144V-1.898H0.528V0H0.946V-1.898Z' id='g1-102'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g3-1'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g0-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g0-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page9'>
+<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -11.54 33.989)'>
+<use x='114.487' xlink:href='#g2-99' y='183.949'/>
+<use x='118.25' xlink:href='#g2-102' y='183.949'/>
+<use x='120.838' xlink:href='#g2-114' y='183.949'/>
+<use x='123.73' xlink:href='#g2-97' y='183.949'/>
+<use x='127.798' xlink:href='#g2-99' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 41.401 33.989)'>
+<use x='114.487' xlink:href='#g2-101' y='183.949'/>
+<use x='118.25' xlink:href='#g2-115' y='183.949'/>
+<use x='121.497' xlink:href='#g2-112' y='183.949'/>
+<use x='125.634' xlink:href='#g2-114' y='183.949'/>
+<use x='128.526' xlink:href='#g2-101' y='183.949'/>
+<use x='132.29' xlink:href='#g2-115' y='183.949'/>
+<use x='135.536' xlink:href='#g2-115' y='183.949'/>
+<use x='138.782' xlink:href='#g2-111' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 103.095 33.989)'>
+<use x='114.487' xlink:href='#g2-98' y='183.949'/>
+<use x='118.859' xlink:href='#g2-97' y='183.949'/>
+<use x='122.692' xlink:href='#g2-114' y='183.949'/>
+<use x='125.584' xlink:href='#g2-110' y='183.949'/>
+<use x='129.957' xlink:href='#g2-101' y='183.949'/>
+<use x='133.72' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 162.903 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-101' y='183.949'/>
+<use x='120.271' xlink:href='#g2-97' y='183.949'/>
+<use x='124.339' xlink:href='#g2-110' y='183.949'/>
+<use x='128.711' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 223.526 33.989)'>
+<use x='114.487' xlink:href='#g2-114' y='183.949'/>
+<use x='117.379' xlink:href='#g2-101' y='183.949'/>
+<use x='121.142' xlink:href='#g2-100' y='183.949'/>
+<use x='125.515' xlink:href='#g2-105' y='183.949'/>
+<use x='127.535' xlink:href='#g2-115' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 277.054 33.989)'>
+<use x='114.487' xlink:href='#g2-108' y='183.949'/>
+<use x='116.507' xlink:href='#g2-97' y='183.949'/>
+<use x='120.34' xlink:href='#g2-114' y='183.949'/>
+<use x='123.232' xlink:href='#g2-115' y='183.949'/>
+<use x='126.478' xlink:href='#g2-111' y='183.949'/>
+<use x='130.712' xlink:href='#g2-110' y='183.949'/>
+<use x='135.085' xlink:href='#g2-78' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 21.624)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.688)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.999)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -72.311)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.622)'>
+<use x='114.487' xlink:href='#g1-50' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-120' y='183.949'/>
+</g>
+<path clip-path='url(#clip9)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M86.328 203.937H89.566V141.316H86.328ZM144.996 203.937H148.234V141.316H144.996ZM203.668 203.937H206.902V141.316H203.668ZM262.336 203.937H265.574V141.316H262.336ZM321.004 203.937H324.242V141.316H321.004ZM379.672 203.937H382.91V141.316H379.672Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M86.328 203.937H89.566V141.316H86.328ZM144.996 203.937H148.234V141.316H144.996ZM203.668 203.937H206.902V141.316H203.668ZM262.336 203.937H265.574V141.316H262.336ZM321.004 203.937H324.242V141.316H321.004ZM379.672 203.937H382.91V141.316H379.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M87.949 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M85.953 141.316H89.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M87.949 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M85.953 141.316H89.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M146.617 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M144.625 141.316H148.61' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M146.617 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M144.625 141.316H148.61' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M205.285 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M203.293 141.316H207.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M205.285 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M203.293 141.316H207.277' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M263.953 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M261.961 141.316H265.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M263.953 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M261.961 141.316H265.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M322.625 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M320.629 141.316H324.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M322.625 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M320.629 141.316H324.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M381.293 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M379.301 141.316H383.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M381.293 141.316V141.316' fill='#f0e0f0'/>
+<path clip-path='url(#clip9)' d='M379.301 141.316H383.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M91.559 203.937H94.797V93.156H91.559ZM150.227 203.937H153.465V78.691H150.227ZM208.899 203.937H212.133V138.246H208.899ZM267.567 203.937H270.805V145.949H267.567ZM326.234 203.937H329.473V130.23H326.234ZM384.902 203.937H388.141V140.25H384.902Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M91.559 203.937H94.797V93.156H91.559ZM150.227 203.937H153.465V78.691H150.227ZM208.899 203.937H212.133V138.246H208.899ZM267.567 203.937H270.805V145.949H267.567ZM326.234 203.937H329.473V130.23H326.234ZM384.902 203.937H388.141V140.25H384.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M93.18 93.156V93.156' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M91.184 93.156H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M93.18 93.156V93.156' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M91.184 93.156H95.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M151.848 78.691V78.691' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M149.855 78.691H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M151.848 78.691V78.691' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M149.855 78.691H153.84' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M210.516 138.246V138.246' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M208.523 138.246H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M210.516 138.246V138.246' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M208.523 138.246H212.507' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M269.184 145.949V145.949' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M267.191 145.949H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M269.184 145.949V145.949' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M267.191 145.949H271.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M327.856 130.23V130.23' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M325.859 130.23H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M327.856 130.23V130.23' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M325.859 130.23H329.847' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M386.524 140.25V140.25' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M384.531 140.25H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M386.524 140.25V140.25' fill='#e1c2e1'/>
+<path clip-path='url(#clip9)' d='M384.531 140.25H388.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M96.789 203.937H100.027V110.816H96.789ZM155.457 203.937H158.695V104.679H155.457ZM214.129 203.937H217.363V139.75H214.129ZM272.797 203.937H276.035V141.254H272.797ZM331.465 203.937H334.703V137.496H331.465ZM390.133 203.937H393.371V132.109H390.133Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M96.789 203.937H100.027V110.816H96.789ZM155.457 203.937H158.695V104.679H155.457ZM214.129 203.937H217.363V139.75H214.129ZM272.797 203.937H276.035V141.254H272.797ZM331.465 203.937H334.703V137.496H331.465ZM390.133 203.937H393.371V132.109H390.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M98.41 110.816V110.816' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M96.414 110.817H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M98.41 110.816V110.816' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M96.414 110.817H100.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M157.078 104.679V104.679' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M155.086 104.68H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M157.078 104.679V104.679' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M155.086 104.68H159.071' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M215.746 139.75V139.75' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M213.754 139.75H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M215.746 139.75V139.75' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M213.754 139.75H217.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M274.414 141.254V141.254' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M272.422 141.254H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M274.414 141.254V141.254' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M272.422 141.254H276.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M333.086 137.496V137.496' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M331.09 137.496H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M333.086 137.496V137.496' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M331.09 137.496H335.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M391.754 132.109V132.109' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M389.762 132.11H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M391.754 132.109V132.109' fill='#d1a3d1'/>
+<path clip-path='url(#clip9)' d='M389.762 132.11H393.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M102.02 203.937H105.258V121.777H102.02ZM160.688 203.937H163.926V110.066H160.688ZM219.359 203.937H222.594V140.312H219.359ZM278.027 203.937H281.266V140.437H278.027ZM336.695 203.937H339.934V138.058H336.695ZM395.363 203.937H398.602V125.16H395.363Z' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M102.02 203.937H105.258V121.777H102.02ZM160.688 203.937H163.926V110.066H160.688ZM219.359 203.937H222.594V140.312H219.359ZM278.027 203.937H281.266V140.437H278.027ZM336.695 203.937H339.934V138.058H336.695ZM395.363 203.937H398.602V125.16H395.363Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M103.641 121.777V121.777' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M101.644 121.777H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M103.641 121.777V121.777' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M101.644 121.777H105.629' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M162.309 110.066V110.066' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M160.316 110.066H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M162.309 110.066V110.066' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M160.316 110.066H164.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M220.977 140.312V140.312' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M218.984 140.312H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M220.977 140.312V140.312' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M218.984 140.312H222.969' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M279.645 140.437V140.437' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M277.652 140.438H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M279.645 140.437V140.437' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M277.652 140.438H281.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M338.317 138.058V138.058' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M336.32 138.059H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M338.317 138.058V138.058' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M336.32 138.059H340.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M396.984 125.16V125.16' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M394.992 125.161H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M396.984 125.16V125.16' fill='#c285c2'/>
+<path clip-path='url(#clip9)' d='M394.992 125.161H398.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M107.25 203.937H110.488V138.433H107.25ZM165.918 203.937H169.156V141.754H165.918ZM224.59 203.937H227.824V141.379H224.59ZM283.258 203.937H286.496V131.172H283.258ZM341.926 203.937H345.164V140.5H341.926ZM400.594 203.937H403.832V134.238H400.594Z' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M107.25 203.937H110.488V138.433H107.25ZM165.918 203.937H169.156V141.754H165.918ZM224.59 203.937H227.824V141.379H224.59ZM283.258 203.937H286.496V131.172H283.258ZM341.926 203.937H345.164V140.5H341.926ZM400.594 203.937H403.832V134.238H400.594Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M108.871 138.433V138.433' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M106.875 138.434H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M108.871 138.433V138.433' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M106.875 138.434H110.86' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M167.539 141.754V141.754' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M165.547 141.754H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M167.539 141.754V141.754' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M165.547 141.754H169.532' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M226.207 141.379V141.379' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M224.215 141.379H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M226.207 141.379V141.379' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M224.215 141.379H228.2' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M284.875 131.172V131.172' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M282.883 131.172H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M284.875 131.172V131.172' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M282.883 131.172H286.868' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M343.547 140.5V140.5' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M341.551 140.5H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M343.547 140.5V140.5' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M341.551 140.5H345.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M402.215 134.238V134.238' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M400.223 134.238H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M402.215 134.238V134.238' fill='#b366b3'/>
+<path clip-path='url(#clip9)' d='M400.223 134.238H404.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M112.481 203.937H115.719V108.687H112.481ZM171.149 203.937H174.387V78.691H171.149ZM229.82 203.937H233.055V139.812H229.82ZM288.488 203.937H291.727V125.785H288.488ZM347.156 203.937H350.395V125.41H347.156ZM405.824 203.937H409.063V131.672H405.824Z' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M112.481 203.937H115.719V108.687H112.481ZM171.149 203.937H174.387V78.691H171.149ZM229.82 203.937H233.055V139.812H229.82ZM288.488 203.937H291.727V125.785H288.488ZM347.156 203.937H350.395V125.41H347.156ZM405.824 203.937H409.063V131.672H405.824Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M114.098 108.687V108.687' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M112.105 108.688H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M114.098 108.687V108.687' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M112.105 108.688H116.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M172.77 78.691V78.691' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M170.777 78.691H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M172.77 78.691V78.691' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M170.777 78.691H174.762' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M231.438 139.812V139.812' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M229.445 139.812H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M231.438 139.812V139.812' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M229.445 139.812H233.43' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M290.106 125.785V125.785' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M288.113 125.785H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M290.106 125.785V125.785' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M288.113 125.785H292.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M348.777 125.41V125.41' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M346.781 125.41H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M348.777 125.41V125.41' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M346.781 125.41H350.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M407.445 131.672V131.672' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M405.453 131.672H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M407.445 131.672V131.672' fill='#a447a4'/>
+<path clip-path='url(#clip9)' d='M405.453 131.672H409.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M117.711 203.937H120.949V141.316H117.711ZM176.379 203.937H179.617V153.402H176.379ZM235.051 203.937H238.285V141.566H235.051ZM293.719 203.937H296.957V131.922H293.719ZM352.387 203.937H355.625V140.562H352.387ZM411.055 203.937H414.293V134.613H411.055Z' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M117.711 203.937H120.949V141.316H117.711ZM176.379 203.937H179.617V153.402H176.379ZM235.051 203.937H238.285V141.566H235.051ZM293.719 203.937H296.957V131.922H293.719ZM352.387 203.937H355.625V140.562H352.387ZM411.055 203.937H414.293V134.613H411.055Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M119.328 141.316V141.316' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M117.336 141.316H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M119.328 141.316V141.316' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M117.336 141.316H121.321' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M178 153.402V153.402' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M176.008 153.403H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M178 153.402V153.402' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M176.008 153.403H179.993' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M236.668 141.566V141.566' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M234.676 141.567H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M236.668 141.566V141.566' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M234.676 141.567H238.661' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M295.336 131.922V131.922' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M293.344 131.922H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M295.336 131.922V131.922' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M293.344 131.922H297.329' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M354.008 140.562V140.562' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M352.012 140.563H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M354.008 140.562V140.562' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M352.012 140.563H356' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M412.676 134.613V134.613' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M410.684 134.614H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M412.676 134.613V134.613' fill='#942994'/>
+<path clip-path='url(#clip9)' d='M410.684 134.614H414.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M122.941 203.937H126.18V116.765H122.941ZM181.609 203.937H184.848V112.32H181.609ZM240.281 203.937H243.516V140.125H240.281ZM298.949 203.937H302.188V131.734H298.949ZM357.617 203.937H360.856V97.168H357.617ZM416.285 203.937H419.524V136.804H416.285Z' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M122.941 203.937H126.18V116.765H122.941ZM181.609 203.937H184.848V112.32H181.609ZM240.281 203.937H243.516V140.125H240.281ZM298.949 203.937H302.188V131.734H298.949ZM357.617 203.937H360.856V97.168H357.617ZM416.285 203.937H419.524V136.804H416.285Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M124.559 116.765V116.765' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M122.566 116.766H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M124.559 116.765V116.765' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M122.566 116.766H126.551' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M183.231 112.32V112.32' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M181.238 112.32H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M183.231 112.32V112.32' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M181.238 112.32H185.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M241.899 140.125V140.125' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M239.906 140.125H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M241.899 140.125V140.125' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M239.906 140.125H243.891' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M300.567 131.734V131.734' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M298.574 131.734H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M300.567 131.734V131.734' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M298.574 131.734H302.559' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M359.238 97.168V97.168' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M357.242 97.168H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M359.238 97.168V97.168' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M357.242 97.168H361.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M417.906 136.804V136.804' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M415.914 136.804H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M417.906 136.804V136.804' fill='#850a85'/>
+<path clip-path='url(#clip9)' d='M415.914 136.804H419.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M128.172 203.937H131.41V104.992H128.172ZM186.84 203.937H190.078V90.09H186.84ZM245.512 203.937H248.746V133.238H245.512ZM362.848 203.937H366.086V124.906H362.848ZM421.516 203.937H424.754V148.453H421.516Z' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M128.172 203.937H131.41V104.992H128.172ZM186.84 203.937H190.078V90.09H186.84ZM245.512 203.937H248.746V133.238H245.512ZM362.848 203.937H366.086V124.906H362.848ZM421.516 203.937H424.754V148.453H421.516Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M129.789 104.992V104.992' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M127.797 104.992H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M129.789 104.992V104.992' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M127.797 104.992H131.782' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M188.461 90.09V90.09' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M186.469 90.09H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M188.461 90.09V90.09' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M186.469 90.09H190.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M247.129 133.238V133.238' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M245.137 133.238H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M247.129 133.238V133.238' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M245.137 133.238H249.122' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M364.469 124.906V124.906' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M362.473 124.906H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M364.469 124.906V124.906' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M362.473 124.906H366.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M423.137 148.453V148.453' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M421.144 148.453H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M423.137 148.453V148.453' fill='#760076'/>
+<path clip-path='url(#clip9)' d='M421.144 148.453H425.128' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M133.402 203.937H136.641V138.746H133.402ZM192.07 203.937H195.309V107.058H192.07ZM250.742 203.937H253.977V141.316H250.742ZM309.41 203.937H312.649V129.355H309.41ZM368.078 203.937H371.317V140.125H368.078ZM426.746 203.937H429.984V140.375H426.746Z' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M133.402 203.937H136.641V138.746H133.402ZM192.07 203.937H195.309V107.058H192.07ZM250.742 203.937H253.977V141.316H250.742ZM309.41 203.937H312.649V129.355H309.41ZM368.078 203.937H371.317V140.125H368.078ZM426.746 203.937H429.984V140.375H426.746Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M135.02 138.746V138.746' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M133.027 138.746H137.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M135.02 138.746V138.746' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M133.027 138.746H137.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M193.692 107.058V107.058' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M191.699 107.058H195.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M193.692 107.058V107.058' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M191.699 107.058H195.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M252.359 141.316V141.316' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M250.367 141.316H254.352' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M252.359 141.316V141.316' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M250.367 141.316H254.352' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M311.027 129.355V129.355' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M309.035 129.355H313.02' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M311.027 129.355V129.355' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M309.035 129.355H313.02' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M369.699 140.125V140.125' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M367.703 140.125H371.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M369.699 140.125V140.125' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M367.703 140.125H371.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M428.367 140.375V140.375' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M426.375 140.375H430.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip9)' d='M428.367 140.375V140.375' fill='#670067'/>
+<path clip-path='url(#clip9)' d='M426.375 140.375H430.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(0 -1 1 0 -94.367 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.698 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 22.971 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 81.64 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.309 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 198.978 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -89.137 201.62)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.468 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-50' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-49' y='183.949'/>
+<use x='126.877' xlink:href='#g1-52' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.201 246.709)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.87 254.412)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.539 238.693)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.208 248.713)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.906 219.28)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.237 213.143)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.432 248.212)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.101 249.715)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 150.77 245.958)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.439 240.572)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.676 230.239)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -20.007 218.529)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 38.662 248.776)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.331 248.901)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 156 246.521)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 214.669 233.621)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -73.445 246.897)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.776 250.216)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-57' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 43.893 249.84)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 102.562 239.633)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.231 248.963)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 219.9 242.701)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -68.215 217.151)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.546 187.155)'>
+<use x='109.598' xlink:href='#g3-1' y='183.949'/>
+<use x='113.103' xlink:href='#g3-1' y='183.949'/>
+<use x='116.608' xlink:href='#g3-1' y='183.949'/>
+<use x='120.114' xlink:href='#g1-52' y='183.949'/>
+<use x='122.76' xlink:href='#g1-46' y='183.949'/>
+<use x='124.23' xlink:href='#g1-53' y='183.949'/>
+<use x='126.877' xlink:href='#g1-50' y='183.949'/>
+<use x='129.523' xlink:href='#g1-120' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.123 248.275)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 107.792 234.247)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.461 233.871)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.13 240.134)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.984 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -4.315 261.864)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-56' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.354 250.028)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.023 240.384)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 171.692 249.026)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.361 243.077)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.754 225.229)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-51' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 0.915 220.783)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-52' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 59.584 248.588)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.253 240.196)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 176.922 205.628)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-55' y='183.949'/>
+<use x='121.25' xlink:href='#g1-49' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 235.591 245.269)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-55' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.524 213.456)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-56' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.145 198.552)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-56' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 64.814 241.699)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-51' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.152 233.37)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-50' y='183.949'/>
+<use x='121.25' xlink:href='#g1-54' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 240.821 256.917)'>
+<use x='114.487' xlink:href='#g1-48' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-56' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -47.293 247.21)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-52' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 11.376 215.523)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-53' y='183.949'/>
+<use x='121.25' xlink:href='#g1-53' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 70.045 249.778)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-48' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.714 237.817)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-49' y='183.949'/>
+<use x='121.25' xlink:href='#g1-57' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 187.383 248.588)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 246.052 248.838)'>
+<use x='114.487' xlink:href='#g1-49' y='183.949'/>
+<use x='117.133' xlink:href='#g1-46' y='183.949'/>
+<use x='118.603' xlink:href='#g1-48' y='183.949'/>
+<use x='121.25' xlink:href='#g1-50' y='183.949'/>
+</g>
+<g transform='matrix(0 -1 1 0 -124.589 307.697)'>
+<use x='114.487' xlink:href='#g0-82' y='183.949'/>
+<use x='120.457' xlink:href='#g0-101' y='183.949'/>
+<use x='124.553' xlink:href='#g0-108' y='183.949'/>
+<use x='126.753' xlink:href='#g0-97' y='183.949'/>
+<use x='131.181' xlink:href='#g0-116' y='183.949'/>
+<use x='134.509' xlink:href='#g0-105' y='183.949'/>
+<use x='136.709' xlink:href='#g0-118' y='183.949'/>
+<use x='140.957' xlink:href='#g0-101' y='183.949'/>
+<use x='148.124' xlink:href='#g0-114' y='183.949'/>
+<use x='151.272' xlink:href='#g0-115' y='183.949'/>
+<use x='154.805' xlink:href='#g0-115' y='183.949'/>
+<use x='161.409' xlink:href='#g2-40' y='183.949'/>
+<use x='164.702' xlink:href='#g2-108' y='183.949'/>
+<use x='166.722' xlink:href='#g2-111' y='183.949'/>
+<use x='170.721' xlink:href='#g2-119' y='183.949'/>
+<use x='176.27' xlink:href='#g2-101' y='183.949'/>
+<use x='180.034' xlink:href='#g2-114' y='183.949'/>
+<use x='185.749' xlink:href='#g2-105' y='183.949'/>
+<use x='187.769' xlink:href='#g2-115' y='183.949'/>
+<use x='193.838' xlink:href='#g2-98' y='183.949'/>
+<use x='198.446' xlink:href='#g2-101' y='183.949'/>
+<use x='202.209' xlink:href='#g2-116' y='183.949'/>
+<use x='205.267' xlink:href='#g2-116' y='183.949'/>
+<use x='208.325' xlink:href='#g2-101' y='183.949'/>
+<use x='212.089' xlink:href='#g2-114' y='183.949'/>
+<use x='214.981' xlink:href='#g2-41' y='183.949'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2020/bench-z4-rss-2.svg b/extlib/mimalloc/doc/bench-2020/bench-z4-rss-2.svg
new file mode 100644 (file)
index 0000000..f426537
--- /dev/null
@@ -0,0 +1,974 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4.2 -->
+<svg height='182.025pt' version='1.1' viewBox='106.736 51.674 381.623 182.025' width='381.623pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<defs>
+<clipPath id='clip10'>
+<path d='M135.949 186.074H487.961V60.828H135.949Z'/>
+</clipPath>
+<use id='g2-40' transform='scale(1.6)' xlink:href='#g1-40'/>
+<use id='g2-41' transform='scale(1.6)' xlink:href='#g1-41'/>
+<use id='g2-45' transform='scale(1.6)' xlink:href='#g1-45'/>
+<use id='g2-49' transform='scale(1.6)' xlink:href='#g1-49'/>
+<use id='g2-54' transform='scale(1.6)' xlink:href='#g1-54'/>
+<use id='g2-56' transform='scale(1.6)' xlink:href='#g1-56'/>
+<use id='g2-78' transform='scale(1.6)' xlink:href='#g1-78'/>
+<use id='g2-97' transform='scale(1.6)' xlink:href='#g1-97'/>
+<use id='g2-98' transform='scale(1.6)' xlink:href='#g1-98'/>
+<use id='g2-99' transform='scale(1.6)' xlink:href='#g1-99'/>
+<use id='g2-100' transform='scale(1.6)' xlink:href='#g1-100'/>
+<use id='g2-101' transform='scale(1.6)' xlink:href='#g1-101'/>
+<use id='g2-103' transform='scale(1.6)' xlink:href='#g1-103'/>
+<use id='g2-104' transform='scale(1.6)' xlink:href='#g1-104'/>
+<use id='g2-105' transform='scale(1.6)' xlink:href='#g1-105'/>
+<use id='g2-106' transform='scale(1.6)' xlink:href='#g1-106'/>
+<use id='g2-108' transform='scale(1.6)' xlink:href='#g1-108'/>
+<use id='g2-109' transform='scale(1.6)' xlink:href='#g1-109'/>
+<use id='g2-110' transform='scale(1.6)' xlink:href='#g1-110'/>
+<use id='g2-111' transform='scale(1.6)' xlink:href='#g1-111'/>
+<use id='g2-112' transform='scale(1.6)' xlink:href='#g1-112'/>
+<use id='g2-114' transform='scale(1.6)' xlink:href='#g1-114'/>
+<use id='g2-115' transform='scale(1.6)' xlink:href='#g1-115'/>
+<use id='g2-116' transform='scale(1.6)' xlink:href='#g1-116'/>
+<use id='g2-119' transform='scale(1.6)' xlink:href='#g1-119'/>
+<use id='g2-120' transform='scale(1.6)' xlink:href='#g1-120'/>
+<path d='M1.519 -3.736C1.435 -3.736 1.425 -3.736 1.365 -3.681C0.737 -3.133 0.418 -2.247 0.418 -1.245C0.418 -0.304 0.702 0.603 1.36 1.181C1.425 1.245 1.435 1.245 1.519 1.245H1.758C1.743 1.235 1.26 0.822 1.031 0.045C0.912 -0.344 0.852 -0.752 0.852 -1.245C0.852 -2.969 1.659 -3.651 1.758 -3.736H1.519Z' id='g1-40'/>
+<path d='M0.533 1.245C0.618 1.245 0.628 1.245 0.687 1.191C1.315 0.643 1.634 -0.244 1.634 -1.245C1.634 -2.187 1.35 -3.093 0.692 -3.671C0.628 -3.736 0.618 -3.736 0.533 -3.736H0.294C0.309 -3.726 0.792 -3.313 1.021 -2.535C1.141 -2.147 1.2 -1.738 1.2 -1.245C1.2 0.478 0.394 1.161 0.294 1.245H0.533Z' id='g1-41'/>
+<path d='M0.956 -0.005V-0.448H0.508V0H0.648L0.503 0.638H0.727L0.956 -0.005Z' id='g1-44'/>
+<path d='M1.465 -0.951V-1.265H0.06V-0.951H1.465Z' id='g1-45'/>
+<path d='M0.956 -0.448H0.508V0H0.956V-0.448Z' id='g1-46'/>
+<path d='M2.431 -1.619C2.431 -1.858 2.431 -2.441 2.197 -2.849C1.943 -3.298 1.559 -3.372 1.32 -3.372C1.096 -3.372 0.707 -3.303 0.458 -2.874C0.219 -2.476 0.209 -1.933 0.209 -1.619C0.209 -1.25 0.229 -0.797 0.438 -0.418C0.658 -0.015 1.026 0.105 1.32 0.105C1.818 0.105 2.092 -0.184 2.242 -0.498C2.416 -0.852 2.431 -1.31 2.431 -1.619ZM1.32 -0.224C1.111 -0.224 0.872 -0.344 0.747 -0.702C0.648 -1.006 0.643 -1.32 0.643 -1.684C0.643 -2.142 0.643 -3.044 1.32 -3.044S1.998 -2.142 1.998 -1.684C1.998 -1.355 1.998 -0.981 1.878 -0.663C1.738 -0.304 1.484 -0.224 1.32 -0.224Z' id='g1-48'/>
+<path d='M1.599 -3.372H1.489C1.166 -3.073 0.757 -3.054 0.458 -3.044V-2.73C0.653 -2.735 0.902 -2.745 1.151 -2.844V-0.314H0.488V0H2.262V-0.314H1.599V-3.372Z' id='g1-49'/>
+<path d='M1.41 -0.384C1.35 -0.384 1.29 -0.379 1.23 -0.379H0.663L1.435 -1.061C1.524 -1.141 1.768 -1.325 1.863 -1.405C2.082 -1.604 2.376 -1.863 2.376 -2.296C2.376 -2.859 1.958 -3.372 1.245 -3.372C0.717 -3.372 0.389 -3.088 0.219 -2.58L0.453 -2.286C0.568 -2.705 0.742 -3.029 1.176 -3.029C1.594 -3.029 1.913 -2.735 1.913 -2.286C1.913 -1.873 1.669 -1.639 1.37 -1.355C1.27 -1.255 1.001 -1.031 0.897 -0.932C0.752 -0.802 0.408 -0.468 0.264 -0.344V0H2.376V-0.384H1.41Z' id='g1-50'/>
+<path d='M0.498 -2.555C0.702 -2.954 1.061 -3.064 1.3 -3.064C1.594 -3.064 1.813 -2.894 1.813 -2.61C1.813 -2.346 1.634 -2.022 1.255 -1.958C1.23 -1.953 1.21 -1.953 0.882 -1.928V-1.599H1.27C1.743 -1.599 1.918 -1.225 1.918 -0.912C1.918 -0.523 1.679 -0.224 1.29 -0.224C0.936 -0.224 0.533 -0.394 0.284 -0.712L0.219 -0.389C0.508 -0.065 0.912 0.105 1.3 0.105C1.953 0.105 2.421 -0.384 2.421 -0.907C2.421 -1.315 2.092 -1.644 1.699 -1.758C2.077 -1.953 2.271 -2.286 2.271 -2.61C2.271 -3.034 1.838 -3.372 1.305 -3.372C0.867 -3.372 0.503 -3.143 0.294 -2.844L0.498 -2.555Z' id='g1-51'/>
+<path d='M1.973 -0.832H2.491V-1.161H1.973V-3.268H1.479L0.149 -1.161V-0.832H1.544V0H1.973V-0.832ZM0.573 -1.161C0.722 -1.395 1.579 -2.725 1.579 -3.024V-1.161H0.573Z' id='g1-52'/>
+<path d='M0.817 -2.924H2.197V-3.268H0.418V-1.405H0.782C0.902 -1.674 1.136 -1.793 1.36 -1.793C1.564 -1.793 1.873 -1.654 1.873 -1.021C1.873 -0.369 1.46 -0.224 1.205 -0.224C0.877 -0.224 0.558 -0.399 0.389 -0.682L0.199 -0.384C0.443 -0.08 0.812 0.105 1.205 0.105C1.863 0.105 2.376 -0.403 2.376 -1.011C2.376 -1.629 1.918 -2.122 1.37 -2.122C1.156 -2.122 0.966 -2.047 0.817 -1.923V-2.924Z' id='g1-53'/>
+<path d='M2.187 -3.273C1.918 -3.372 1.729 -3.372 1.634 -3.372C0.877 -3.372 0.219 -2.66 0.219 -1.609C0.219 -0.259 0.827 0.105 1.33 0.105C1.733 0.105 1.943 -0.085 2.097 -0.244C2.416 -0.583 2.421 -0.936 2.421 -1.111C2.421 -1.763 2.067 -2.306 1.584 -2.306C1.096 -2.306 0.832 -2.052 0.687 -1.908C0.752 -2.59 1.101 -3.064 1.639 -3.064C1.738 -3.064 1.938 -3.054 2.187 -2.959V-3.273ZM0.692 -1.096C0.692 -1.126 0.692 -1.2 0.697 -1.225C0.697 -1.564 0.912 -1.978 1.355 -1.978C1.963 -1.978 1.963 -1.28 1.963 -1.111C1.963 -0.922 1.963 -0.712 1.828 -0.503C1.709 -0.324 1.559 -0.224 1.33 -0.224C0.802 -0.224 0.717 -0.877 0.692 -1.096Z' id='g1-54'/>
+<path d='M1.23 -2.884C1.29 -2.884 1.35 -2.889 1.41 -2.889H2.037C1.28 -2.147 0.797 -1.106 0.797 0.05H1.265C1.265 -1.405 1.973 -2.451 2.421 -2.919V-3.268H0.219V-2.884H1.23Z' id='g1-55'/>
+<path d='M1.704 -1.763C2.032 -1.868 2.346 -2.132 2.346 -2.501C2.346 -2.954 1.913 -3.372 1.32 -3.372S0.294 -2.954 0.294 -2.501C0.294 -2.127 0.618 -1.863 0.936 -1.763C0.498 -1.629 0.219 -1.29 0.219 -0.907C0.219 -0.374 0.692 0.105 1.32 0.105S2.421 -0.374 2.421 -0.907C2.421 -1.29 2.137 -1.629 1.704 -1.763ZM1.32 -1.928C0.966 -1.928 0.677 -2.132 0.677 -2.496C0.677 -2.814 0.902 -3.064 1.32 -3.064C1.733 -3.064 1.963 -2.814 1.963 -2.496C1.963 -2.142 1.684 -1.928 1.32 -1.928ZM1.32 -0.224C0.976 -0.224 0.672 -0.443 0.672 -0.912C0.672 -1.36 0.961 -1.599 1.32 -1.599S1.968 -1.355 1.968 -0.912C1.968 -0.443 1.659 -0.224 1.32 -0.224Z' id='g1-56'/>
+<path d='M0.384 -0.125C0.628 0.055 0.852 0.105 1.086 0.105C1.783 0.105 2.421 -0.598 2.421 -1.669C2.421 -3.029 1.818 -3.372 1.34 -3.372C0.897 -3.372 0.692 -3.163 0.548 -3.019C0.229 -2.695 0.219 -2.351 0.219 -2.157C0.219 -1.514 0.568 -0.961 1.056 -0.961C1.619 -0.961 1.928 -1.335 1.953 -1.365C1.883 -0.573 1.494 -0.224 1.086 -0.224C0.827 -0.224 0.667 -0.319 0.553 -0.413L0.384 -0.125ZM1.938 -2.162C1.943 -2.132 1.943 -2.082 1.943 -2.052C1.943 -1.684 1.719 -1.29 1.285 -1.29C1.096 -1.29 0.946 -1.345 0.817 -1.549C0.687 -1.743 0.677 -1.933 0.677 -2.157C0.677 -2.351 0.677 -2.575 0.832 -2.795C0.936 -2.944 1.086 -3.064 1.335 -3.064C1.818 -3.064 1.923 -2.481 1.938 -2.162Z' id='g1-57'/>
+<path d='M2.959 -0.438C2.884 -0.438 2.874 -0.438 2.834 -0.418C2.59 -0.334 2.336 -0.279 2.072 -0.279C1.27 -0.279 0.697 -0.956 0.697 -1.729C0.697 -2.565 1.345 -3.178 2.042 -3.178C2.182 -3.178 2.511 -3.143 2.675 -2.745C2.535 -2.824 2.381 -2.859 2.252 -2.859C1.719 -2.859 1.27 -2.361 1.27 -1.729C1.27 -1.081 1.733 -0.598 2.247 -0.598C2.635 -0.598 3.228 -0.912 3.228 -1.798C3.228 -2.301 3.193 -3.507 2.047 -3.507C1.101 -3.507 0.294 -2.725 0.294 -1.729C0.294 -0.742 1.091 0.05 2.052 0.05C2.511 0.05 2.939 -0.139 3.228 -0.438H2.959ZM2.252 -0.927C1.943 -0.927 1.674 -1.27 1.674 -1.729C1.674 -2.202 1.953 -2.531 2.247 -2.531C2.555 -2.531 2.824 -2.187 2.824 -1.729C2.824 -1.255 2.545 -0.927 2.252 -0.927Z' id='g1-64'/>
+<path d='M3.083 -0.608C2.735 -0.394 2.575 -0.299 2.077 -0.299C1.305 -0.299 0.837 -1.021 0.837 -1.738C0.837 -2.476 1.35 -3.168 2.077 -3.168C2.406 -3.168 2.745 -3.064 2.974 -2.889L3.054 -3.342C2.705 -3.472 2.426 -3.512 2.062 -3.512C1.076 -3.512 0.339 -2.695 0.339 -1.733C0.339 -0.707 1.121 0.05 2.092 0.05C2.58 0.05 2.785 -0.05 3.113 -0.229L3.083 -0.608Z' id='g1-67'/>
+<path d='M2.725 -1.624V-1.953H0.986V-3.098H1.714C1.773 -3.098 1.833 -3.093 1.893 -3.093H2.874V-3.442H0.483V0H2.949V-0.389H2.501C2.082 -0.389 1.664 -0.379 1.245 -0.379H0.986V-1.624H2.725Z' id='g1-69'/>
+<path d='M3.173 -1.489H2.057V-1.161H2.735V-0.399C2.516 -0.344 2.301 -0.299 2.077 -0.299C1.31 -0.299 0.837 -1.021 0.837 -1.733C0.837 -2.416 1.3 -3.168 2.052 -3.168C2.511 -3.168 2.8 -3.029 3.049 -2.819L3.128 -3.273C2.785 -3.437 2.481 -3.517 2.102 -3.517C1.096 -3.517 0.339 -2.73 0.339 -1.733C0.339 -0.762 1.091 0.05 2.072 0.05C2.431 0.05 2.854 -0.03 3.173 -0.194V-1.489Z' id='g1-71'/>
+<path d='M3.248 -3.457H2.745V-1.963H0.986V-3.457H0.483V0H0.986V-1.634H2.745V0H3.248V-3.457Z' id='g1-72'/>
+<path d='M0.986 -3.457H0.483V0H0.986V-3.457Z' id='g1-73'/>
+<path d='M1.176 -3.457H0.498V0H0.917V-3.064H0.922L2.555 0H3.233V-3.457H2.814V-0.394H2.809L1.176 -3.457Z' id='g1-78'/>
+<path d='M3.611 -1.714C3.611 -2.745 2.854 -3.562 1.953 -3.562S0.294 -2.745 0.294 -1.714S1.061 0.105 1.953 0.105C2.849 0.105 3.611 -0.687 3.611 -1.714ZM1.953 -0.249C1.35 -0.249 0.797 -0.852 0.797 -1.793C0.797 -2.675 1.355 -3.218 1.953 -3.218S3.108 -2.675 3.108 -1.793C3.108 -0.847 2.555 -0.249 1.953 -0.249Z' id='g1-79'/>
+<path d='M1.868 -1.42C2.511 -1.42 3.083 -1.873 3.083 -2.446C3.083 -2.979 2.555 -3.457 1.833 -3.457H0.488V0H0.991V-1.42H1.868ZM1.709 -3.163C2.271 -3.163 2.63 -2.864 2.63 -2.446C2.63 -2.037 2.291 -1.729 1.709 -1.729H0.976V-3.163H1.709Z' id='g1-80'/>
+<path d='M3.143 -3.457H2.71V-1.161C2.71 -0.493 2.262 -0.189 1.833 -0.189S0.986 -0.498 0.986 -1.156V-3.457H0.483V-1.166C0.483 -0.433 1.111 0.105 1.828 0.105C2.54 0.105 3.143 -0.438 3.143 -1.166V-3.457Z' id='g1-85'/>
+<path d='M1.968 -1.823L3.228 -3.457H2.685L1.724 -2.182L0.742 -3.457H0.149L1.479 -1.823L0.075 0H0.618L1.724 -1.499L2.854 0H3.447L1.968 -1.823Z' id='g1-88'/>
+<path d='M2.934 -3.238V-3.457H0.369V-3.123H1.41C1.479 -3.123 1.539 -3.128 1.609 -3.128H2.291L0.294 -0.229V0H2.964V-0.354H2.466C1.958 -0.354 1.45 -0.344 0.941 -0.344L2.934 -3.238Z' id='g1-90'/>
+<path d='M2.122 -1.435C2.122 -1.943 1.733 -2.286 1.24 -2.286C0.927 -2.286 0.687 -2.222 0.408 -2.072L0.438 -1.709C0.603 -1.818 0.847 -1.968 1.24 -1.968C1.46 -1.968 1.689 -1.803 1.689 -1.43V-1.23C0.951 -1.205 0.224 -1.051 0.224 -0.588C0.224 -0.339 0.394 0.05 0.832 0.05C1.046 0.05 1.44 0.005 1.704 -0.189V0H2.122V-1.435ZM1.689 -0.707C1.689 -0.608 1.689 -0.478 1.514 -0.374C1.355 -0.284 1.161 -0.279 1.106 -0.279C0.832 -0.279 0.623 -0.403 0.623 -0.593C0.623 -0.912 1.465 -0.941 1.689 -0.951V-0.707Z' id='g1-97'/>
+<path d='M0.842 -3.457H0.423V0H0.857V-0.234C0.966 -0.139 1.205 0.05 1.569 0.05C2.112 0.05 2.55 -0.458 2.55 -1.111C2.55 -1.714 2.207 -2.262 1.709 -2.262C1.395 -2.262 1.091 -2.162 0.842 -1.978V-3.457ZM0.857 -1.569C0.857 -1.649 0.857 -1.709 1.031 -1.823C1.106 -1.868 1.24 -1.933 1.41 -1.933C1.743 -1.933 2.117 -1.709 2.117 -1.111C2.117 -0.503 1.704 -0.279 1.355 -0.279C1.171 -0.279 0.996 -0.364 0.857 -0.588V-1.569Z' id='g1-98'/>
+<path d='M2.167 -0.543C1.918 -0.384 1.649 -0.294 1.34 -0.294C0.882 -0.294 0.613 -0.663 0.613 -1.111C0.613 -1.494 0.812 -1.943 1.355 -1.943C1.694 -1.943 1.853 -1.873 2.107 -1.714L2.172 -2.072C1.873 -2.222 1.743 -2.286 1.355 -2.286C0.608 -2.286 0.179 -1.684 0.179 -1.106C0.179 -0.498 0.658 0.05 1.335 0.05C1.684 0.05 1.983 -0.055 2.197 -0.179L2.167 -0.543Z' id='g1-99'/>
+<path d='M2.306 -3.457H1.888V-1.998C1.569 -2.232 1.245 -2.262 1.101 -2.262C0.578 -2.262 0.179 -1.738 0.179 -1.106S0.573 0.05 1.086 0.05C1.395 0.05 1.684 -0.09 1.873 -0.259V0H2.306V-3.457ZM1.873 -0.618C1.748 -0.413 1.559 -0.279 1.32 -0.279C0.971 -0.279 0.613 -0.523 0.613 -1.101C0.613 -1.724 1.036 -1.933 1.375 -1.933C1.574 -1.933 1.743 -1.848 1.873 -1.679V-0.618Z' id='g1-100'/>
+<path d='M2.142 -0.543C1.863 -0.344 1.549 -0.279 1.335 -0.279C0.902 -0.279 0.573 -0.633 0.558 -1.091H2.192C2.192 -1.32 2.167 -1.654 1.973 -1.938C1.793 -2.192 1.494 -2.286 1.25 -2.286C0.643 -2.286 0.174 -1.753 0.174 -1.121C0.174 -0.483 0.672 0.05 1.33 0.05C1.619 0.05 1.918 -0.035 2.172 -0.189L2.142 -0.543ZM0.593 -1.39C0.707 -1.788 1.001 -1.958 1.25 -1.958C1.469 -1.958 1.793 -1.853 1.888 -1.39H0.593Z' id='g1-101'/>
+<path d='M2.506 -2.262C2.396 -2.262 2.062 -2.257 1.684 -2.112L1.674 -2.107C1.494 -2.227 1.32 -2.262 1.176 -2.262C0.687 -2.262 0.324 -1.878 0.324 -1.45C0.324 -1.275 0.384 -1.096 0.498 -0.956C0.428 -0.872 0.354 -0.732 0.354 -0.543C0.354 -0.349 0.433 -0.224 0.478 -0.164C0.204 -0.005 0.149 0.224 0.149 0.344C0.149 0.722 0.672 1.021 1.32 1.021C1.973 1.021 2.491 0.722 2.491 0.344C2.491 -0.359 1.619 -0.359 1.405 -0.359H0.941C0.862 -0.359 0.648 -0.359 0.648 -0.618C0.648 -0.717 0.682 -0.767 0.687 -0.777C0.862 -0.667 1.036 -0.633 1.171 -0.633C1.659 -0.633 2.022 -1.016 2.022 -1.445C2.022 -1.604 1.978 -1.748 1.888 -1.883C1.868 -1.913 1.868 -1.918 1.868 -1.923C1.868 -1.943 2.167 -1.943 2.192 -1.943C2.197 -1.943 2.386 -1.943 2.565 -1.923L2.506 -2.262ZM1.176 -0.941C0.907 -0.941 0.707 -1.111 0.707 -1.445C0.707 -1.833 0.956 -1.953 1.171 -1.953C1.44 -1.953 1.639 -1.783 1.639 -1.45C1.639 -1.061 1.39 -0.941 1.176 -0.941ZM1.41 0.03C1.524 0.03 2.112 0.03 2.112 0.349C2.112 0.563 1.738 0.712 1.32 0.712S0.528 0.563 0.528 0.349C0.528 0.324 0.528 0.03 0.932 0.03H1.41Z' id='g1-103'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.161 -2.262 0.932 -2.012 0.832 -1.908V-3.457H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-104'/>
+<path d='M0.877 -3.417H0.374V-2.914H0.877V-3.417ZM0.837 -2.212H0.418V0H0.837V-2.212Z' id='g1-105'/>
+<path d='M0.986 -3.417H0.483V-2.914H0.986V-3.417ZM-0.324 0.847C-0.095 0.971 0.13 1.016 0.319 1.016C0.663 1.016 0.986 0.752 0.986 0.294V-2.212H0.568V0.329C0.568 0.418 0.568 0.498 0.463 0.583C0.349 0.667 0.209 0.667 0.164 0.667C-0.045 0.667 -0.174 0.573 -0.234 0.518L-0.324 0.847Z' id='g1-106'/>
+<path d='M0.837 -3.457H0.418V0H0.837V-3.457Z' id='g1-108'/>
+<path d='M3.786 -1.474C3.786 -1.863 3.671 -2.262 3.059 -2.262C2.64 -2.262 2.381 -2.017 2.262 -1.858C2.212 -1.993 2.087 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.21C2.316 -1.539 2.456 -1.933 2.839 -1.933C3.352 -1.933 3.352 -1.584 3.352 -1.44V0H3.786V-1.474Z' id='g1-109'/>
+<path d='M2.316 -1.474C2.316 -1.863 2.202 -2.262 1.589 -2.262C1.305 -2.262 1.031 -2.147 0.812 -1.883V-2.247H0.413V0H0.847V-1.21C0.847 -1.539 0.986 -1.933 1.37 -1.933C1.883 -1.933 1.883 -1.584 1.883 -1.44V0H2.316V-1.474Z' id='g1-110'/>
+<path d='M2.491 -1.091C2.491 -1.748 1.968 -2.286 1.32 -2.286S0.149 -1.743 0.149 -1.091C0.149 -0.458 0.677 0.05 1.32 0.05C1.968 0.05 2.491 -0.458 2.491 -1.091ZM1.32 -0.294C0.927 -0.294 0.583 -0.583 0.583 -1.146S0.951 -1.958 1.32 -1.958C1.694 -1.958 2.057 -1.699 2.057 -1.146C2.057 -0.578 1.704 -0.294 1.32 -0.294Z' id='g1-111'/>
+<path d='M0.857 -0.234C1.121 0.005 1.405 0.05 1.574 0.05C2.102 0.05 2.55 -0.453 2.55 -1.111C2.55 -1.709 2.222 -2.262 1.729 -2.262C1.504 -2.262 1.131 -2.197 0.842 -1.973V-2.212H0.423V0.966H0.857V-0.234ZM0.857 -1.654C0.971 -1.793 1.166 -1.918 1.405 -1.918C1.803 -1.918 2.117 -1.549 2.117 -1.111C2.117 -0.618 1.743 -0.279 1.355 -0.279C1.28 -0.279 1.156 -0.289 1.026 -0.394C0.877 -0.508 0.857 -0.583 0.857 -0.677V-1.654Z' id='g1-112'/>
+<path d='M0.842 -1.061C0.842 -1.599 1.29 -1.888 1.729 -1.893V-2.262C1.31 -2.257 1.006 -2.052 0.807 -1.788V-2.247H0.423V0H0.842V-1.061Z' id='g1-114'/>
+<path d='M1.818 -2.132C1.479 -2.271 1.23 -2.286 1.051 -2.286C0.927 -2.286 0.174 -2.286 0.174 -1.624C0.174 -1.39 0.304 -1.26 0.369 -1.2C0.543 -1.026 0.752 -0.986 1.016 -0.936C1.25 -0.892 1.519 -0.842 1.519 -0.603C1.519 -0.289 1.106 -0.289 1.036 -0.289C0.717 -0.289 0.418 -0.403 0.219 -0.543L0.149 -0.169C0.319 -0.085 0.623 0.05 1.036 0.05C1.26 0.05 1.479 0.015 1.664 -0.12C1.848 -0.259 1.908 -0.478 1.908 -0.648C1.908 -0.737 1.898 -0.932 1.689 -1.121C1.504 -1.285 1.325 -1.32 1.086 -1.365C0.792 -1.42 0.563 -1.465 0.563 -1.684C0.563 -1.968 0.927 -1.968 1.001 -1.968C1.285 -1.968 1.504 -1.908 1.753 -1.778L1.818 -2.132Z' id='g1-115'/>
+<path d='M0.936 -1.898H1.674V-2.212H0.936V-2.844H0.553V-2.212H0.1V-1.898H0.538V-0.638C0.538 -0.304 0.623 0.05 0.981 0.05S1.614 -0.065 1.763 -0.134L1.679 -0.453C1.514 -0.334 1.34 -0.294 1.2 -0.294C0.991 -0.294 0.936 -0.498 0.936 -0.727V-1.898Z' id='g1-116'/>
+<path d='M2.316 -2.212H1.883V-0.767C1.883 -0.369 1.544 -0.244 1.255 -0.244C0.887 -0.244 0.847 -0.344 0.847 -0.573V-2.212H0.413V-0.543C0.413 -0.1 0.608 0.05 0.956 0.05C1.161 0.05 1.599 0.01 1.898 -0.229V0H2.316V-2.212Z' id='g1-117'/>
+<path d='M3.537 -2.212H3.148C3.103 -2.072 2.824 -1.23 2.67 -0.712C2.63 -0.568 2.58 -0.408 2.565 -0.294H2.56C2.531 -0.498 2.356 -1.036 2.346 -1.071L1.978 -2.212H1.599C1.455 -1.783 1.081 -0.667 1.041 -0.304H1.036C0.996 -0.658 0.628 -1.758 0.548 -1.998C0.508 -2.117 0.508 -2.127 0.483 -2.212H0.075L0.802 0H1.22C1.225 -0.02 1.36 -0.413 1.534 -0.966C1.609 -1.21 1.758 -1.689 1.783 -1.908L1.788 -1.913C1.798 -1.808 1.828 -1.699 1.863 -1.574S1.933 -1.315 1.968 -1.2L2.351 0H2.809L3.537 -2.212Z' id='g1-119'/>
+<path d='M1.38 -1.141L2.346 -2.212H1.908L1.2 -1.395L0.478 -2.212H0.03L1.026 -1.141L0 0H0.443L1.2 -0.936L1.988 0H2.436L1.38 -1.141Z' id='g1-120'/>
+<path d='M2.112 -2.002V-2.212H0.219V-1.893H0.951C1.011 -1.893 1.071 -1.898 1.131 -1.898H1.519L0.149 -0.219V0H2.127V-0.334H1.355C1.295 -0.334 1.235 -0.329 1.176 -0.329H0.742L2.112 -2.002Z' id='g1-122'/>
+<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g0-82'/>
+<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g0-97'/>
+<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g0-101'/>
+<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g0-105'/>
+<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g0-108'/>
+<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g0-114'/>
+<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g0-115'/>
+<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g0-116'/>
+<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g0-118'/>
+</defs>
+<g id='page10'>
+<path d='M194.617 194.93V186.074M253.285 194.93V186.074M311.953 194.93V186.074M370.625 194.93V186.074M429.293 194.93V186.074M194.617 51.973V60.828M253.285 51.973V60.828M311.953 51.973V60.828M370.625 51.973V60.828M429.293 51.973V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M165.281 190.324V186.074M223.953 190.324V186.074M282.621 190.324V186.074M341.289 190.324V186.074M399.957 190.324V186.074M458.629 190.324V186.074M165.281 56.574V60.828M223.953 56.574V60.828M282.621 56.574V60.828M341.289 56.574V60.828M399.957 56.574V60.828M458.629 56.574V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 186.074H140.199M135.949 154.762H140.199M135.949 123.449H140.199M135.949 92.141H140.199M135.949 60.828H140.199M487.961 186.074H483.711M487.961 154.762H483.711M487.961 123.449H483.711M487.961 92.141H483.711M487.961 60.828H483.711' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
+<path d='M135.949 186.074V60.828H487.961V186.074H135.949Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -21.265 59.571)'>
+<use x='168.285' xlink:href='#g2-97' y='140.503'/>
+<use x='172.353' xlink:href='#g2-108' y='140.503'/>
+<use x='174.373' xlink:href='#g2-108' y='140.503'/>
+<use x='176.393' xlink:href='#g2-111' y='140.503'/>
+<use x='180.863' xlink:href='#g2-99' y='140.503'/>
+<use x='184.627' xlink:href='#g2-45' y='140.503'/>
+<use x='187.449' xlink:href='#g2-116' y='140.503'/>
+<use x='190.507' xlink:href='#g2-101' y='140.503'/>
+<use x='194.271' xlink:href='#g2-115' y='140.503'/>
+<use x='197.517' xlink:href='#g2-116' y='140.503'/>
+<use x='200.575' xlink:href='#g2-49' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 59.571)'>
+<use x='168.285' xlink:href='#g2-97' y='140.503'/>
+<use x='172.353' xlink:href='#g2-108' y='140.503'/>
+<use x='174.373' xlink:href='#g2-108' y='140.503'/>
+<use x='176.393' xlink:href='#g2-111' y='140.503'/>
+<use x='180.863' xlink:href='#g2-99' y='140.503'/>
+<use x='184.627' xlink:href='#g2-45' y='140.503'/>
+<use x='187.449' xlink:href='#g2-116' y='140.503'/>
+<use x='190.507' xlink:href='#g2-101' y='140.503'/>
+<use x='194.271' xlink:href='#g2-115' y='140.503'/>
+<use x='197.517' xlink:href='#g2-116' y='140.503'/>
+<use x='200.575' xlink:href='#g2-78' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 59.571)'>
+<use x='168.285' xlink:href='#g2-115' y='140.503'/>
+<use x='171.531' xlink:href='#g2-104' y='140.503'/>
+<use x='175.904' xlink:href='#g2-54' y='140.503'/>
+<use x='180.138' xlink:href='#g2-98' y='140.503'/>
+<use x='184.746' xlink:href='#g2-101' y='140.503'/>
+<use x='188.509' xlink:href='#g2-110' y='140.503'/>
+<use x='192.882' xlink:href='#g2-99' y='140.503'/>
+<use x='196.646' xlink:href='#g2-104' y='140.503'/>
+<use x='201.018' xlink:href='#g2-78' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 59.571)'>
+<use x='168.285' xlink:href='#g2-115' y='140.503'/>
+<use x='171.531' xlink:href='#g2-104' y='140.503'/>
+<use x='175.904' xlink:href='#g2-56' y='140.503'/>
+<use x='180.138' xlink:href='#g2-98' y='140.503'/>
+<use x='184.746' xlink:href='#g2-101' y='140.503'/>
+<use x='188.509' xlink:href='#g2-110' y='140.503'/>
+<use x='192.882' xlink:href='#g2-99' y='140.503'/>
+<use x='196.646' xlink:href='#g2-104' y='140.503'/>
+<use x='201.018' xlink:href='#g2-78' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 59.571)'>
+<use x='168.285' xlink:href='#g2-120' y='140.503'/>
+<use x='172.187' xlink:href='#g2-109' y='140.503'/>
+<use x='178.912' xlink:href='#g2-97' y='140.503'/>
+<use x='182.98' xlink:href='#g2-108' y='140.503'/>
+<use x='185' xlink:href='#g2-108' y='140.503'/>
+<use x='187.02' xlink:href='#g2-111' y='140.503'/>
+<use x='191.49' xlink:href='#g2-99' y='140.503'/>
+<use x='195.254' xlink:href='#g2-45' y='140.503'/>
+<use x='198.076' xlink:href='#g2-116' y='140.503'/>
+<use x='201.134' xlink:href='#g2-101' y='140.503'/>
+<use x='204.898' xlink:href='#g2-115' y='140.503'/>
+<use x='208.144' xlink:href='#g2-116' y='140.503'/>
+<use x='211.202' xlink:href='#g2-78' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 59.571)'>
+<use x='168.285' xlink:href='#g2-99' y='140.503'/>
+<use x='172.049' xlink:href='#g2-97' y='140.503'/>
+<use x='176.117' xlink:href='#g2-99' y='140.503'/>
+<use x='179.88' xlink:href='#g2-104' y='140.503'/>
+<use x='184.253' xlink:href='#g2-101' y='140.503'/>
+<use x='188.017' xlink:href='#g2-45' y='140.503'/>
+<use x='190.839' xlink:href='#g2-115' y='140.503'/>
+<use x='194.086' xlink:href='#g2-99' y='140.503'/>
+<use x='197.849' xlink:href='#g2-114' y='140.503'/>
+<use x='200.741' xlink:href='#g2-97' y='140.503'/>
+<use x='204.81' xlink:href='#g2-116' y='140.503'/>
+<use x='207.868' xlink:href='#g2-99' y='140.503'/>
+<use x='211.631' xlink:href='#g2-104' y='140.503'/>
+<use x='216.004' xlink:href='#g2-78' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 47.205)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 15.894)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -15.418)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -46.729)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.041)'>
+<use x='168.285' xlink:href='#g1-50' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-120' y='140.503'/>
+</g>
+<path clip-path='url(#clip10)' d='M135.949 123.449H487.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M140.125 186.074H143.363V123.449H140.125ZM198.797 186.074H202.035V123.449H198.797ZM257.465 186.074H260.703V123.449H257.465ZM316.133 186.074H319.371V123.449H316.133ZM374.801 186.074H378.039V123.449H374.801ZM433.473 186.074H436.711V123.449H433.473Z' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M140.125 186.074H143.363V123.449H140.125ZM198.797 186.074H202.035V123.449H198.797ZM257.465 186.074H260.703V123.449H257.465ZM316.133 186.074H319.371V123.449H316.133ZM374.801 186.074H378.039V123.449H374.801ZM433.473 186.074H436.711V123.449H433.473Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M141.746 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M139.754 123.449H143.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M141.746 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M139.754 123.449H143.738' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M200.414 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M198.422 123.449H202.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M200.414 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M198.422 123.449H202.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M259.082 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M257.09 123.449H261.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M259.082 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M257.09 123.449H261.078' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M317.754 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M315.762 123.449H319.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M317.754 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M315.762 123.449H319.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M376.422 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M374.43 123.449H378.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M376.422 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M374.43 123.449H378.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M435.09 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M433.098 123.449H437.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M435.09 123.449V123.449' fill='#f0e0f0'/>
+<path clip-path='url(#clip10)' d='M433.098 123.449H437.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M145.356 186.074H148.594V120.071H145.356ZM204.028 186.074H207.266V121.571H204.028ZM262.695 186.074H265.934V122.699H262.695ZM321.363 186.074H324.602V125.895H321.363ZM380.031 186.074H383.27V173.172H380.031ZM438.703 186.074H441.942V93.391H438.703Z' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M145.356 186.074H148.594V120.071H145.356ZM204.028 186.074H207.266V121.571H204.028ZM262.695 186.074H265.934V122.699H262.695ZM321.363 186.074H324.602V125.895H321.363ZM380.031 186.074H383.27V173.172H380.031ZM438.703 186.074H441.942V93.391H438.703Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M146.977 120.071V120.071' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M144.984 120.07H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M146.977 120.071V120.071' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M144.984 120.07H148.968' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M205.645 121.571V121.571' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M203.652 121.57H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M205.645 121.571V121.571' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M203.652 121.57H207.636' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M264.313 122.699V122.699' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M262.32 122.699H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M264.313 122.699V122.699' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M262.32 122.699H266.308' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M322.984 125.895V125.895' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M320.992 125.894H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M322.984 125.895V125.895' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M320.992 125.894H324.976' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M381.652 173.172V173.172' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M379.66 173.172H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M381.652 173.172V173.172' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M379.66 173.172H383.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M440.32 93.391V93.391' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M438.328 93.391H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M440.32 93.391V93.391' fill='#e1c2e1'/>
+<path clip-path='url(#clip10)' d='M438.328 93.391H442.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M150.586 186.074H153.824V122.699H150.586ZM209.258 186.074H212.496V124.766H209.258ZM267.926 186.074H271.164V121.762H267.926ZM326.594 186.074H329.832V118.692H326.594ZM385.262 186.074H388.5V154.324H385.262ZM443.934 186.074H447.172V111.238H443.934Z' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M150.586 186.074H153.824V122.699H150.586ZM209.258 186.074H212.496V124.766H209.258ZM267.926 186.074H271.164V121.762H267.926ZM326.594 186.074H329.832V118.692H326.594ZM385.262 186.074H388.5V154.324H385.262ZM443.934 186.074H447.172V111.238H443.934Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M152.207 122.699V122.699' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M150.215 122.699H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M152.207 122.699V122.699' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M150.215 122.699H154.199' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M210.875 124.766V124.766' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M208.883 124.766H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M210.875 124.766V124.766' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M208.883 124.766H212.867' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M269.543 121.762V121.762' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M267.551 121.762H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M269.543 121.762V121.762' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M267.551 121.762H271.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M328.215 118.692V118.692' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M326.223 118.691H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M328.215 118.692V118.692' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M326.223 118.691H330.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M386.883 154.324V154.324' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M384.891 154.324H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M386.883 154.324V154.324' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M384.891 154.324H388.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M445.551 111.238V111.238' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M443.559 111.238H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M445.551 111.238V111.238' fill='#d1a3d1'/>
+<path clip-path='url(#clip10)' d='M443.559 111.238H447.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M155.817 186.074H159.055V119.696H155.817ZM214.488 186.074H217.727V121.887H214.488ZM273.156 186.074H276.395V113.43H273.156ZM331.824 186.074H335.063V119.004H331.824ZM390.492 186.074H393.731V89.133H390.492ZM449.164 186.074H452.402V120.633H449.164Z' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M155.817 186.074H159.055V119.696H155.817ZM214.488 186.074H217.727V121.887H214.488ZM273.156 186.074H276.395V113.43H273.156ZM331.824 186.074H335.063V119.004H331.824ZM390.492 186.074H393.731V89.133H390.492ZM449.164 186.074H452.402V120.633H449.164Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M157.438 119.696V119.696' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M155.445 119.695H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M157.438 119.696V119.696' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M155.445 119.695H159.429' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M216.106 121.887V121.887' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M214.113 121.886H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M216.106 121.887V121.887' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M214.113 121.886H218.097' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M274.774 113.43V113.43' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M272.781 113.43H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M274.774 113.43V113.43' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M272.781 113.43H276.769' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M333.445 119.004V119.004' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M331.453 119.004H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M333.445 119.004V119.004' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M331.453 119.004H335.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M392.113 89.133V89.133' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M390.121 89.133H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M392.113 89.133V89.133' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M390.121 89.133H394.105' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M450.781 120.633V120.633' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M448.789 120.633H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M450.781 120.633V120.633' fill='#c285c2'/>
+<path clip-path='url(#clip10)' d='M448.789 120.633H452.773' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M161.047 186.074H164.285V109.738H161.047ZM219.719 186.074H222.957V112.555H219.719ZM278.387 186.074H281.625V86.192H278.387ZM337.055 186.074H340.293V106.543H337.055ZM395.723 186.074H398.961V172.172H395.723ZM454.395 186.074H457.633V122.949H454.395Z' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M161.047 186.074H164.285V109.738H161.047ZM219.719 186.074H222.957V112.555H219.719ZM278.387 186.074H281.625V86.192H278.387ZM337.055 186.074H340.293V106.543H337.055ZM395.723 186.074H398.961V172.172H395.723ZM454.395 186.074H457.633V122.949H454.395Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M162.668 109.738V109.738' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M160.676 109.738H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M162.668 109.738V109.738' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M160.676 109.738H164.66' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M221.336 112.555V112.555' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M219.344 112.554H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M221.336 112.555V112.555' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M219.344 112.554H223.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M280.004 86.192V86.192' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M278.012 86.191H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M280.004 86.192V86.192' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M278.012 86.191H282' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M338.676 106.543V106.543' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M336.684 106.543H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M338.676 106.543V106.543' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M336.684 106.543H340.668' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M397.344 172.172V172.172' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M395.352 172.172H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M397.344 172.172V172.172' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M395.352 172.172H399.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M456.012 122.949V122.949' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M454.02 122.949H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M456.012 122.949V122.949' fill='#b366b3'/>
+<path clip-path='url(#clip10)' d='M454.02 122.949H458.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M166.278 186.074H169.516V98.278H166.278ZM224.949 186.074H228.188V94.77H224.949ZM283.617 186.074H286.856V78.051H283.617ZM342.285 186.074H345.524V92.453H342.285ZM400.953 186.074H404.192V154.762H400.953ZM459.625 186.074H462.863V113.242H459.625Z' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M166.278 186.074H169.516V98.278H166.278ZM224.949 186.074H228.188V94.77H224.949ZM283.617 186.074H286.856V78.051H283.617ZM342.285 186.074H345.524V92.453H342.285ZM400.953 186.074H404.192V154.762H400.953ZM459.625 186.074H462.863V113.242H459.625Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M167.899 98.278V98.278' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M165.906 98.277H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M167.899 98.278V98.278' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M165.906 98.277H169.89' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M226.567 94.77V94.77' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M224.574 94.77H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M226.567 94.77V94.77' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M224.574 94.77H228.558' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M285.234 78.051V78.051' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M283.242 78.051H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M285.234 78.051V78.051' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M283.242 78.051H287.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M343.906 92.453V92.453' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M341.914 92.453H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M343.906 92.453V92.453' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M341.914 92.453H345.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M402.574 154.762V154.762' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M400.582 154.761H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M402.574 154.762V154.762' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M400.582 154.761H404.566' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M461.242 113.242V113.242' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M459.25 113.242H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M461.242 113.242V113.242' fill='#a447a4'/>
+<path clip-path='url(#clip10)' d='M459.25 113.242H463.234' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M171.508 186.074H174.746V109.172H171.508ZM230.18 186.074H233.414V112.617H230.18ZM288.848 186.074H292.086V86.254H288.848ZM347.516 186.074H350.754V107.418H347.516ZM406.184 186.074H409.422V172.235H406.184ZM464.856 186.074H468.094V124.266H464.856Z' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M171.508 186.074H174.746V109.172H171.508ZM230.18 186.074H233.414V112.617H230.18ZM288.848 186.074H292.086V86.254H288.848ZM347.516 186.074H350.754V107.418H347.516ZM406.184 186.074H409.422V172.235H406.184ZM464.856 186.074H468.094V124.266H464.856Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M173.129 109.172V109.172' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M171.137 109.172H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M173.129 109.172V109.172' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M171.137 109.172H175.121' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M231.797 112.617V112.617' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M229.805 112.617H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M231.797 112.617V112.617' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M229.805 112.617H233.789' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M290.465 86.254V86.254' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M288.473 86.254H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M290.465 86.254V86.254' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M288.473 86.254H292.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M349.137 107.418V107.418' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M347.145 107.418H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M349.137 107.418V107.418' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M347.145 107.418H351.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M407.805 172.235V172.235' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M405.813 172.234H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M407.805 172.235V172.235' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M405.813 172.234H409.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M466.473 124.266V124.266' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M464.481 124.266H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M466.473 124.266V124.266' fill='#942994'/>
+<path clip-path='url(#clip10)' d='M464.481 124.266H468.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M411.414 186.074H414.652V151.946H411.414ZM176.738 186.074H179.977V117.375H176.738ZM235.41 186.074H238.645V119.567H235.41ZM294.078 186.074H297.317V116.813H294.078ZM352.746 186.074H355.984V123.891H352.746ZM470.086 186.074H473.324V117.313H470.086Z' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M411.414 186.074H414.652V151.946H411.414ZM176.738 186.074H179.977V117.375H176.738ZM235.41 186.074H238.645V119.567H235.41ZM294.078 186.074H297.317V116.813H294.078ZM352.746 186.074H355.984V123.891H352.746ZM470.086 186.074H473.324V117.313H470.086Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M413.035 151.946V151.946' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M411.043 151.945H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M413.035 151.946V151.946' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M411.043 151.945H415.027' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M178.36 117.375V117.375' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M176.367 117.375H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M178.36 117.375V117.375' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M176.367 117.375H180.351' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M237.027 119.567V119.567' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M235.035 119.566H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M237.027 119.567V119.567' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M235.035 119.566H239.019' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M295.695 116.813V116.813' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M293.703 116.813H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M295.695 116.813V116.813' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M293.703 116.813H297.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M354.367 123.891V123.891' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M352.375 123.89H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M354.367 123.891V123.891' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M352.375 123.89H356.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M471.703 117.313V117.313' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M469.711 117.313H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M471.703 117.313V117.313' fill='#850a85'/>
+<path clip-path='url(#clip10)' d='M469.711 117.313H473.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M181.969 186.074H185.207V121.762H181.969ZM240.641 186.074H243.875V122.074H240.641ZM299.309 186.074H302.547V122.574H299.309ZM357.977 186.074H361.215V121.949H357.977ZM475.317 186.074H478.555V113.746H475.317Z' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M181.969 186.074H185.207V121.762H181.969ZM240.641 186.074H243.875V122.074H240.641ZM299.309 186.074H302.547V122.574H299.309ZM357.977 186.074H361.215V121.949H357.977ZM475.317 186.074H478.555V113.746H475.317Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M183.59 121.762V121.762' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M181.598 121.762H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M183.59 121.762V121.762' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M181.598 121.762H185.583' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M242.258 122.074V122.074' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M240.266 122.074H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M242.258 122.074V122.074' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M240.266 122.074H244.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M300.926 122.574V122.574' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M298.933 122.574H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M300.926 122.574V122.574' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M298.933 122.574H302.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M359.598 121.949V121.949' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M357.606 121.949H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M359.598 121.949V121.949' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M357.606 121.949H361.59' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M476.934 113.746V113.746' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M474.942 113.746H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M476.934 113.746V113.746' fill='#760076'/>
+<path clip-path='url(#clip10)' d='M474.942 113.746H478.926' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M187.199 186.074H190.438V122.887H187.199ZM245.871 186.074H249.106V122.637H245.871ZM304.539 186.074H307.777V123.387H304.539ZM363.207 186.074H366.445V125.391H363.207ZM421.875 186.074H425.113V169.164H421.875ZM480.547 186.074H483.785V121.571H480.547Z' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M187.199 186.074H190.438V122.887H187.199ZM245.871 186.074H249.106V122.637H245.871ZM304.539 186.074H307.777V123.387H304.539ZM363.207 186.074H366.445V125.391H363.207ZM421.875 186.074H425.113V169.164H421.875ZM480.547 186.074H483.785V121.571H480.547Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M188.82 122.887V122.887' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M186.828 122.886H190.813' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M188.82 122.887V122.887' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M186.828 122.886H190.813' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M247.488 122.637V122.637' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M245.496 122.637H249.481' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M247.488 122.637V122.637' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M245.496 122.637H249.481' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M306.156 123.387V123.387' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M304.164 123.387H308.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M306.156 123.387V123.387' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M304.164 123.387H308.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M364.828 125.391V125.391' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M362.836 125.39H366.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M364.828 125.391V125.391' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M362.836 125.39H366.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M423.496 169.164V169.164' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M421.504 169.164H425.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M423.496 169.164V169.164' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M421.504 169.164H425.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M482.164 121.571V121.571' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M480.172 121.57H484.156' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M482.164 121.571V121.571' fill='#670067'/>
+<path clip-path='url(#clip10)' d='M480.172 121.57H484.156' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path clip-path='url(#clip10)' d='M419.477 233.301H487.762V211.324H419.477Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 254.512 88.837)'>
+<use x='168.285' xlink:href='#g1-72' y='129.265'/>
+<use x='172.021' xlink:href='#g1-80' y='129.265'/>
+<use x='175.402' xlink:href='#g1-45' y='129.265'/>
+<use x='177.167' xlink:href='#g1-90' y='129.265'/>
+<use x='180.401' xlink:href='#g1-52' y='129.265'/>
+<use x='183.047' xlink:href='#g1-45' y='129.265'/>
+<use x='184.812' xlink:href='#g1-71' y='129.265'/>
+<use x='188.34' xlink:href='#g1-52' y='129.265'/>
+<use x='190.987' xlink:href='#g1-44' y='129.265'/>
+<use x='194.221' xlink:href='#g1-49' y='129.265'/>
+<use x='196.867' xlink:href='#g1-54' y='129.265'/>
+<use x='199.514' xlink:href='#g1-71' y='129.265'/>
+<use x='203.042' xlink:href='#g1-98' y='129.265'/>
+<use x='168.285' xlink:href='#g1-56' y='134.884'/>
+<use x='170.931' xlink:href='#g1-45' y='134.884'/>
+<use x='172.695' xlink:href='#g1-99' y='134.884'/>
+<use x='175.048' xlink:href='#g1-111' y='134.884'/>
+<use x='177.547' xlink:href='#g1-114' y='134.884'/>
+<use x='179.355' xlink:href='#g1-101' y='134.884'/>
+<use x='183.471' xlink:href='#g1-73' y='134.884'/>
+<use x='184.941' xlink:href='#g1-110' y='134.884'/>
+<use x='187.674' xlink:href='#g1-116' y='134.884'/>
+<use x='189.585' xlink:href='#g1-101' y='134.884'/>
+<use x='191.938' xlink:href='#g1-108' y='134.884'/>
+<use x='194.965' xlink:href='#g1-88' y='134.884'/>
+<use x='198.493' xlink:href='#g1-69' y='134.884'/>
+<use x='201.667' xlink:href='#g1-79' y='134.884'/>
+<use x='205.576' xlink:href='#g1-78' y='134.884'/>
+<use x='211.076' xlink:href='#g1-64' y='134.884'/>
+<use x='214.605' xlink:href='#g1-50' y='134.884'/>
+<use x='217.251' xlink:href='#g1-46' y='134.884'/>
+<use x='218.721' xlink:href='#g1-55' y='134.884'/>
+<use x='221.368' xlink:href='#g1-71' y='134.884'/>
+<use x='224.896' xlink:href='#g1-104' y='134.884'/>
+<use x='227.629' xlink:href='#g1-122' y='134.884'/>
+<use x='168.285' xlink:href='#g1-85' y='140.503'/>
+<use x='171.917' xlink:href='#g1-98' y='140.503'/>
+<use x='174.65' xlink:href='#g1-117' y='140.503'/>
+<use x='177.383' xlink:href='#g1-110' y='140.503'/>
+<use x='180.116' xlink:href='#g1-116' y='140.503'/>
+<use x='182.027' xlink:href='#g1-117' y='140.503'/>
+<use x='186.524' xlink:href='#g1-49' y='140.503'/>
+<use x='189.17' xlink:href='#g1-56' y='140.503'/>
+<use x='191.817' xlink:href='#g1-46' y='140.503'/>
+<use x='193.287' xlink:href='#g1-48' y='140.503'/>
+<use x='195.933' xlink:href='#g1-52' y='140.503'/>
+<use x='198.58' xlink:href='#g1-46' y='140.503'/>
+<use x='200.05' xlink:href='#g1-49' y='140.503'/>
+<use x='202.696' xlink:href='#g1-44' y='140.503'/>
+<use x='205.931' xlink:href='#g1-71' y='140.503'/>
+<use x='209.459' xlink:href='#g1-67' y='140.503'/>
+<use x='212.841' xlink:href='#g1-67' y='140.503'/>
+<use x='217.986' xlink:href='#g1-55' y='140.503'/>
+<use x='220.633' xlink:href='#g1-46' y='140.503'/>
+<use x='222.103' xlink:href='#g1-52' y='140.503'/>
+<use x='224.749' xlink:href='#g1-46' y='140.503'/>
+<use x='226.219' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 2.877 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 61.546 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 120.215 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 178.884 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 237.553 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 296.222 285.711)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 8.107 282.329)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-53' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 66.776 283.832)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 125.445 284.96)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 184.114 288.153)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 242.783 335.434)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 301.452 255.652)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-52' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 13.338 284.96)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 72.007 287.026)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.676 284.02)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 189.345 280.952)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-56' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 248.014 316.584)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 306.683 273.5)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.568 281.954)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 77.237 284.146)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.906 275.691)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.575 281.265)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 253.244 251.394)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-53' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 311.913 282.893)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-52' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.799 271.997)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.468 274.815)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 141.137 248.45)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-54' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.806 268.803)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 258.475 334.432)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 317.144 285.21)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 29.029 260.537)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-52' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.698 257.03)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-52' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.367 240.309)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-55' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 205.036 254.713)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-52' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 263.705 317.023)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 322.374 275.504)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 34.26 271.433)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.929 274.877)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.598 248.513)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 210.267 269.68)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 268.936 334.494)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 327.605 286.525)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 274.166 314.205)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-53' y='140.503'/>
+<use x='175.048' xlink:href='#g1-52' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.49 279.637)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 98.159 281.828)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.828 279.073)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.497 286.149)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-57' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 332.835 279.574)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.72 284.02)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.389 284.333)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 162.058 284.834)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.727 284.208)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-50' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 338.065 276.005)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-49' y='140.503'/>
+<use x='175.048' xlink:href='#g1-54' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.951 285.147)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.62 284.897)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-49' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 167.289 285.648)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-48' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.958 287.652)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-57' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 284.627 331.426)'>
+<use x='168.285' xlink:href='#g1-48' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-50' y='140.503'/>
+<use x='175.048' xlink:href='#g1-55' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 343.296 283.832)'>
+<use x='168.285' xlink:href='#g1-49' y='140.503'/>
+<use x='170.931' xlink:href='#g1-46' y='140.503'/>
+<use x='172.401' xlink:href='#g1-48' y='140.503'/>
+<use x='175.048' xlink:href='#g1-51' y='140.503'/>
+</g>
+<g transform='matrix(0 -1 1 0 -27.345 343.63)'>
+<use x='168.285' xlink:href='#g0-82' y='140.503'/>
+<use x='174.255' xlink:href='#g0-101' y='140.503'/>
+<use x='178.351' xlink:href='#g0-108' y='140.503'/>
+<use x='180.551' xlink:href='#g0-97' y='140.503'/>
+<use x='184.979' xlink:href='#g0-116' y='140.503'/>
+<use x='188.307' xlink:href='#g0-105' y='140.503'/>
+<use x='190.507' xlink:href='#g0-118' y='140.503'/>
+<use x='194.755' xlink:href='#g0-101' y='140.503'/>
+<use x='201.922' xlink:href='#g0-114' y='140.503'/>
+<use x='205.07' xlink:href='#g0-115' y='140.503'/>
+<use x='208.603' xlink:href='#g0-115' y='140.503'/>
+<use x='215.207' xlink:href='#g2-40' y='140.503'/>
+<use x='218.5' xlink:href='#g2-108' y='140.503'/>
+<use x='220.521' xlink:href='#g2-111' y='140.503'/>
+<use x='224.52' xlink:href='#g2-119' y='140.503'/>
+<use x='230.068' xlink:href='#g2-101' y='140.503'/>
+<use x='233.832' xlink:href='#g2-114' y='140.503'/>
+<use x='239.547' xlink:href='#g2-105' y='140.503'/>
+<use x='241.567' xlink:href='#g2-115' y='140.503'/>
+<use x='247.636' xlink:href='#g2-98' y='140.503'/>
+<use x='252.244' xlink:href='#g2-101' y='140.503'/>
+<use x='256.008' xlink:href='#g2-116' y='140.503'/>
+<use x='259.066' xlink:href='#g2-116' y='140.503'/>
+<use x='262.124' xlink:href='#g2-101' y='140.503'/>
+<use x='265.887' xlink:href='#g2-114' y='140.503'/>
+<use x='268.779' xlink:href='#g2-41' y='140.503'/>
+</g>
+<path d='M136.149 231.446H402.137V214.453H136.149Z' fill='#ffffff'/>
+<path d='M136.149 231.446H402.137V214.453H136.149Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<path d='M139.336 224.941H142.324V216.972H139.336ZM145.313 224.941H148.301V218.964H145.313Z' fill='#f0e0f0'/>
+<path d='M139.336 224.941H142.324V216.972H139.336ZM145.313 224.941H148.301V218.964H145.313Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -33.522 84.43)'>
+<use x='185.011' xlink:href='#g2-109' y='140.503'/>
+<use x='191.736' xlink:href='#g2-105' y='140.503'/>
+</g>
+<path d='M163.422 224.941H166.41V216.973H163.422ZM169.398 224.941H172.391V218.965H169.398Z' fill='#e1c2e1'/>
+<path d='M163.422 224.941H166.41V216.972H163.422ZM169.398 224.941H172.391V218.964H169.398Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.56 83.976)'>
+<use x='208.137' xlink:href='#g2-116' y='140.503'/>
+<use x='211.195' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M185.586 224.941H188.574V216.973H185.586ZM191.563 224.941H194.555V218.965H191.563Z' fill='#d1a3d1'/>
+<path d='M185.586 224.941H188.574V216.972H185.586ZM191.563 224.941H194.555V218.964H191.563Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.159 84.43)'>
+<use x='229.9' xlink:href='#g2-106' y='140.503'/>
+<use x='232.155' xlink:href='#g2-101' y='140.503'/>
+</g>
+<path d='M206.949 224.941H209.938V216.973H206.949ZM212.926 224.941H215.914V218.965H212.926Z' fill='#c285c2'/>
+<path d='M206.949 224.941H209.938V216.972H206.949ZM212.926 224.941H215.914V218.964H212.926Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.958 83.47)'>
+<use x='252.061' xlink:href='#g2-115' y='140.503'/>
+<use x='255.307' xlink:href='#g2-110' y='140.503'/>
+</g>
+<path d='M229.91 224.941H232.898V216.973H229.91ZM235.887 224.941H238.875V218.965H235.887Z' fill='#b366b3'/>
+<path d='M229.91 224.941H232.898V216.972H229.91ZM235.887 224.941H238.875V218.964H235.887Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -32.781 83.47)'>
+<use x='274.845' xlink:href='#g2-114' y='140.503'/>
+<use x='277.737' xlink:href='#g2-112' y='140.503'/>
+</g>
+<path d='M252.516 224.941H255.504V216.973H252.516ZM258.496 224.941H261.484V218.965H258.496Z' fill='#a447a4'/>
+<path d='M252.516 224.941H255.504V216.972H252.516ZM258.496 224.941H261.484V218.964H258.496Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -39.001 84.467)'>
+<use x='303.672' xlink:href='#g2-104' y='140.503'/>
+<use x='308.045' xlink:href='#g2-111' y='140.503'/>
+<use x='312.279' xlink:href='#g2-97' y='140.503'/>
+<use x='316.112' xlink:href='#g2-114' y='140.503'/>
+<use x='319.004' xlink:href='#g2-100' y='140.503'/>
+</g>
+<path d='M287.563 224.941H290.551V216.973H287.563ZM293.543 224.941H296.531V218.965H293.543Z' fill='#942994'/>
+<path d='M287.563 224.941H290.551V216.972H287.563ZM293.543 224.941H296.531V218.964H293.543Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -37.472 84.467)'>
+<use x='337.19' xlink:href='#g2-103' y='140.503'/>
+<use x='341.424' xlink:href='#g2-108' y='140.503'/>
+<use x='343.444' xlink:href='#g2-105' y='140.503'/>
+<use x='345.464' xlink:href='#g2-98' y='140.503'/>
+<use x='350.072' xlink:href='#g2-99' y='140.503'/>
+</g>
+<path d='M319.551 224.941H322.539V216.973H319.551ZM325.527 224.941H328.52V218.965H325.527Z' fill='#850a85'/>
+<path d='M319.551 224.941H322.539V216.972H319.551ZM325.527 224.941H328.52V218.964H325.527Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.051 84.467)'>
+<use x='366.757' xlink:href='#g2-116' y='140.503'/>
+<use x='369.815' xlink:href='#g2-98' y='140.503'/>
+<use x='374.187' xlink:href='#g2-98' y='140.503'/>
+</g>
+<path d='M346.699 224.941H349.688V216.973H346.699ZM352.676 224.941H355.664V218.965H352.676Z' fill='#760076'/>
+<path d='M346.699 224.941H349.688V216.972H346.699ZM352.676 224.941H355.664V218.964H352.676Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -34.135 83.47)'>
+<use x='392.986' xlink:href='#g2-115' y='140.503'/>
+<use x='396.233' xlink:href='#g2-109' y='140.503'/>
+</g>
+<path d='M372.012 224.941H375V216.973H372.012ZM377.988 224.941H380.977V218.965H377.988Z' fill='#670067'/>
+<path d='M372.012 224.941H375V216.972H372.012ZM377.988 224.941H380.977V218.964H377.988Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
+<g transform='matrix(1 0 0 1 -35.145 84.43)'>
+<use x='419.31' xlink:href='#g2-115' y='140.503'/>
+<use x='422.556' xlink:href='#g2-109' y='140.503'/>
+<use x='429.281' xlink:href='#g2-105' y='140.503'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg b/extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg
new file mode 100644 (file)
index 0000000..86a97bf
--- /dev/null
@@ -0,0 +1,952 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.629pt' height='170.383pt' viewBox='52.934 54.994 381.629 170.383'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip1'>
+<path d='M82.148 209.23H434.164V83.984H82.148Z'/>
+</clipPath>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-102' xlink:href='#g0-102' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-109' d='M6.581-2.663C6.581-3.327 6.402-4.08 5.317-4.08C4.564-4.08 4.142-3.622 3.927-3.344C3.865-3.524 3.676-4.08 2.762-4.08C2.053-4.08 1.623-3.667 1.417-3.398V-4.035H.726V0H1.47V-2.188C1.47-2.78 1.704-3.497 2.385-3.497C3.282-3.497 3.282-2.86 3.282-2.6V0H4.026V-2.188C4.026-2.78 4.259-3.497 4.94-3.497C5.837-3.497 5.837-2.86 5.837-2.6V0H6.581V-2.663Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-102' d='M1.325-2.657H2.12V-3.096H1.304V-3.898C1.304-4.38 1.743-4.449 1.974-4.449C2.12-4.449 2.308-4.428 2.566-4.331V-4.84C2.385-4.882 2.169-4.91 1.981-4.91C1.262-4.91 .739-4.394 .739-3.703V-3.096H.202V-2.657H.739V0H1.325V-2.657Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+</defs>
+<g id='page1'>
+<path d='M140.82 218.086V209.23M199.488 218.086V209.23M258.156 218.086V209.23M316.824 218.086V209.23M375.496 218.086V209.23M140.82 75.129V83.984M199.488 75.129V83.984M258.156 75.129V83.984M316.824 75.129V83.984M375.496 75.129V83.984' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M111.484 213.484V209.23M170.152 213.484V209.23M228.824 213.484V209.23M287.492 213.484V209.23M346.16 213.484V209.23M404.828 213.484V209.23M111.484 79.734V83.984M170.152 79.734V83.984M228.824 79.734V83.984M287.492 79.734V83.984M346.16 79.734V83.984M404.828 79.734V83.984' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 209.23H86.402M82.148 177.918H86.402M82.148 146.609H86.402M82.148 115.297H86.402M82.148 83.984H86.402M434.164 209.23H429.91M434.164 177.918H429.91M434.164 146.609H429.91M434.164 115.297H429.91M434.164 83.984H429.91' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 209.23V83.984H434.164V209.23H82.148Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-99'/>
+<use x='118.25' y='188.674' xlink:href='#g3-102'/>
+<use x='120.838' y='188.674' xlink:href='#g3-114'/>
+<use x='123.73' y='188.674' xlink:href='#g3-97'/>
+<use x='127.798' y='188.674' xlink:href='#g3-99'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-108'/>
+<use x='116.507' y='188.674' xlink:href='#g3-101'/>
+<use x='120.271' y='188.674' xlink:href='#g3-97'/>
+<use x='124.339' y='188.674' xlink:href='#g3-110'/>
+<use x='128.711' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-114'/>
+<use x='117.379' y='188.674' xlink:href='#g3-101'/>
+<use x='121.142' y='188.674' xlink:href='#g3-100'/>
+<use x='125.515' y='188.674' xlink:href='#g3-105'/>
+<use x='127.535' y='188.674' xlink:href='#g3-115'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-108'/>
+<use x='116.507' y='188.674' xlink:href='#g3-97'/>
+<use x='120.34' y='188.674' xlink:href='#g3-114'/>
+<use x='123.232' y='188.674' xlink:href='#g3-115'/>
+<use x='126.478' y='188.674' xlink:href='#g3-111'/>
+<use x='130.712' y='188.674' xlink:href='#g3-110'/>
+<use x='135.085' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-109'/>
+<use x='121.211' y='188.674' xlink:href='#g3-115'/>
+<use x='124.458' y='188.674' xlink:href='#g3-116'/>
+<use x='127.516' y='188.674' xlink:href='#g3-114'/>
+<use x='130.408' y='188.674' xlink:href='#g3-101'/>
+<use x='134.171' y='188.674' xlink:href='#g3-115'/>
+<use x='137.418' y='188.674' xlink:href='#g3-115'/>
+<use x='140.664' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-114'/>
+<use x='117.379' y='188.674' xlink:href='#g3-112'/>
+<use x='121.751' y='188.674' xlink:href='#g3-116'/>
+<use x='124.809' y='188.674' xlink:href='#g3-101'/>
+<use x='128.573' y='188.674' xlink:href='#g3-115'/>
+<use x='131.819' y='188.674' xlink:href='#g3-116'/>
+<use x='134.877' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
+<use x='114.487' y='188.674' xlink:href='#g2-50'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<path d='M82.148 146.609H434.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M86.328 209.23H89.566V146.609H86.328ZM144.996 209.23H148.234V146.609H144.996ZM203.668 209.23H206.902V146.609H203.668ZM262.336 209.23H265.574V146.609H262.336ZM321.004 209.23H324.242V146.609H321.004ZM379.672 209.23H382.91V146.609H379.672Z' fill='#933' clip-path='url(#clip1)'/>
+<path d='M86.328 209.23H89.566V146.609H86.328ZM144.996 209.23H148.234V146.609H144.996ZM203.668 209.23H206.902V146.609H203.668ZM262.336 209.23H265.574V146.609H262.336ZM321.004 209.23H324.242V146.609H321.004ZM379.672 209.23H382.91V146.609H379.672Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M87.949 146.609V146.484' fill='#933' clip-path='url(#clip1)'/>
+<path d='M87.949 146.609V146.484' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M85.953 146.484H89.938' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M87.949 146.609V146.734' fill='#933' clip-path='url(#clip1)'/>
+<path d='M87.949 146.609V146.734' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M89.941 146.734H85.957' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M146.617 146.609V146.359' fill='#933' clip-path='url(#clip1)'/>
+<path d='M146.617 146.609V146.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M144.625 146.36H148.609' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M146.617 146.609V146.859' fill='#933' clip-path='url(#clip1)'/>
+<path d='M146.617 146.609V146.859' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M148.61 146.86H144.625' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M205.285 146.609V146.297' fill='#933' clip-path='url(#clip1)'/>
+<path d='M205.285 146.609V146.297' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M203.293 146.297H207.277' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M205.285 146.609V146.922' fill='#933' clip-path='url(#clip1)'/>
+<path d='M205.285 146.609V146.922' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M207.278 146.922H203.293' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M263.953 146.609V146.422' fill='#933' clip-path='url(#clip1)'/>
+<path d='M263.953 146.609V146.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M261.961 146.422H265.945' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M263.953 146.609V146.797' fill='#933' clip-path='url(#clip1)'/>
+<path d='M263.953 146.609V146.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M265.949 146.797H261.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M322.625 146.609V146.168' fill='#933' clip-path='url(#clip1)'/>
+<path d='M322.625 146.609V146.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M320.629 146.168H324.617' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M322.625 146.609V147.047' fill='#933' clip-path='url(#clip1)'/>
+<path d='M322.625 146.609V147.047' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M324.617 147.046H320.633' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M381.293 146.609V145.168' fill='#933' clip-path='url(#clip1)'/>
+<path d='M381.293 146.609V145.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M379.301 145.168H383.285' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M381.293 146.609V148.047' fill='#933' clip-path='url(#clip1)'/>
+<path d='M381.293 146.609V148.047' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M383.285 148.046H379.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M91.559 209.23H94.797V147.172H91.559ZM150.227 209.23H153.465V145.48H150.227ZM208.899 209.23H212.133V146.797H208.899ZM267.567 209.23H270.805V149.051H267.567ZM326.234 209.23H329.473V146.359H326.234ZM384.902 209.23H388.141V132.707H384.902Z' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M91.559 209.23H94.797V147.172H91.559ZM150.227 209.23H153.465V145.48H150.227ZM208.899 209.23H212.133V146.797H208.899ZM267.567 209.23H270.805V149.051H267.567ZM326.234 209.23H329.473V146.359H326.234ZM384.902 209.23H388.141V132.707H384.902Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M93.18 147.172V146.922' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M93.18 147.172V146.922' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M91.184 146.922H95.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M93.18 147.172V147.422' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M93.18 147.172V147.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M95.172 147.422H91.187' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M151.848 145.48V145.23' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M151.848 145.48V145.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M149.855 145.23H153.84' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M151.848 145.48V145.73' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M151.848 145.48V145.73' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M153.84 145.73H149.855' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M210.516 146.797V146.484' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M210.516 146.797V146.484' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M208.523 146.484H212.507' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M210.516 146.797V147.109' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M210.516 146.797V147.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M212.508 147.109H208.523' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.184 149.051V148.426' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M269.184 149.051V148.426' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M267.191 148.426H271.175' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.184 149.051V149.676' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M269.184 149.051V149.676' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M271.179 149.676H267.191' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M327.856 146.359V144.164' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M327.856 146.359V144.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M325.859 144.164H329.847' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M327.856 146.359V148.551' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M327.856 146.359V148.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M329.847 148.55H325.863' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M386.524 132.707V129.137' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M386.524 132.707V129.137' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M384.531 129.136H388.515' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M386.524 132.707V136.273' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M386.524 132.707V136.273' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M388.515 136.273H384.531' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M96.789 209.23H100.027V146.359H96.789ZM155.457 209.23H158.695V138.781H155.457ZM214.129 209.23H217.363V142.476H214.129ZM272.797 209.23H276.035V135.086H272.797ZM331.465 209.23H334.703V146.922H331.465ZM390.133 209.23H393.371V83.984H390.133Z' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M96.789 209.23H100.027V146.359H96.789ZM155.457 209.23H158.695V138.781H155.457ZM214.129 209.23H217.363V142.476H214.129ZM272.797 209.23H276.035V135.086H272.797ZM331.465 209.23H334.703V146.922H331.465ZM390.133 209.23H393.371V83.984H390.133Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M98.41 146.359V146.043' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M98.41 146.359V146.043' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M96.414 146.043H100.399' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M98.41 146.359V146.672' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M98.41 146.359V146.672' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M100.402 146.672H96.418' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M157.078 138.781V138.469' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M157.078 138.781V138.469' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M155.086 138.469H159.071' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M157.078 138.781V139.094' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M157.078 138.781V139.094' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M159.071 139.093H155.086' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M215.746 142.476V142.289' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M215.746 142.476V142.289' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M213.754 142.289H217.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M215.746 142.476V142.664' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M215.746 142.476V142.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M217.739 142.664H213.754' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.414 135.086V132.957' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M274.414 135.086V132.957' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M272.422 132.957H276.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.414 135.086V137.215' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M274.414 135.086V137.215' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M276.41 137.215H272.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M333.086 146.922V145.73' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M333.086 146.922V145.73' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M331.09 145.73H335.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M333.086 146.922V148.109' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M333.086 146.922V148.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M335.078 148.109H331.094' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M391.754 83.984' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M389.762 83.984H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M391.754 83.984' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M389.762 83.984H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M102.02 209.23H105.258V142.223H102.02ZM160.688 209.23H163.926V143.851H160.688ZM219.359 209.23H222.594V137.277H219.359ZM278.027 209.23H281.266V131.328H278.027ZM336.695 209.23H339.934V120.934H336.695ZM395.363 209.23H398.602V83.984H395.363Z' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M102.02 209.23H105.258V142.223H102.02ZM160.688 209.23H163.926V143.851H160.688ZM219.359 209.23H222.594V137.277H219.359ZM278.027 209.23H281.266V131.328H278.027ZM336.695 209.23H339.934V120.934H336.695ZM395.363 209.23H398.602V83.984H395.363Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M103.641 142.223V142.098' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M103.641 142.223V142.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M101.644 142.097H105.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M103.641 142.223V142.351' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M103.641 142.223V142.351' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M105.633 142.352H101.648' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M162.309 143.851V143.101' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M162.309 143.851V143.101' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M160.316 143.101H164.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M162.309 143.851V144.605' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M162.309 143.851V144.605' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M164.301 144.605H160.316' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M220.977 137.277V136.902' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M220.977 137.277V136.902' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M218.984 136.903H222.969' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M220.977 137.277V137.652' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M220.977 137.277V137.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M222.969 137.652H218.984' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.645 131.328V130.516' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M279.645 131.328V130.516' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M277.652 130.516H281.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.645 131.328V132.141' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M279.645 131.328V132.141' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M281.64 132.14H277.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M338.317 120.934V120.305' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M338.317 120.934V120.305' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M336.32 120.304H340.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M338.317 120.934V121.559' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M338.317 120.934V121.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M340.308 121.559H336.324' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M396.984 83.984' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M394.992 83.984H398.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M396.984 83.984' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M394.992 83.984H398.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M107.25 209.23H110.488V120.367H107.25ZM165.918 209.23H169.156V137.777H165.918ZM224.59 209.23H227.824V111.789H224.59ZM283.258 209.23H286.496V92.187H283.258ZM341.926 209.23H345.164V134.019H341.926ZM400.594 209.23H403.832V118.051H400.594Z' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M107.25 209.23H110.488V120.367H107.25ZM165.918 209.23H169.156V137.777H165.918ZM224.59 209.23H227.824V111.789H224.59ZM283.258 209.23H286.496V92.187H283.258ZM341.926 209.23H345.164V134.019H341.926ZM400.594 209.23H403.832V118.051H400.594Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.871 120.367V119.992' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M108.871 120.367V119.992' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M106.875 119.992H110.86' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.871 120.367V120.746' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M108.871 120.367V120.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M110.864 120.746H106.879' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M167.539 137.777V137.527' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M167.539 137.777V137.527' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M165.547 137.528H169.532' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M167.539 137.777V138.027' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M167.539 137.777V138.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M169.532 138.028H165.547' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M226.207 111.789V111.726' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M226.207 111.789V111.726' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M224.215 111.726H228.2' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M226.207 111.789V111.851' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M226.207 111.789V111.851' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M228.2 111.851H224.215' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.875 92.187V90.308' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M284.875 92.187V90.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M282.883 90.309H286.868' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.875 92.187V94.066' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M284.875 92.187V94.066' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M286.868 94.066H282.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M343.547 134.019V132.894' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M343.547 134.019V132.894' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M341.551 132.895H345.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M343.547 134.019V135.148' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M343.547 134.019V135.148' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M345.539 135.148H341.555' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M402.215 118.051V112.289' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M402.215 118.051V112.289' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M400.223 112.289H404.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M402.215 118.051V123.812' fill='#bf80bf' clip-path='url(#clip1)'/>
+<path d='M402.215 118.051V123.812' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M404.207 123.812H400.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M112.481 209.23H115.719V145.918H112.481ZM171.149 209.23H174.387V145.105H171.149ZM229.82 209.23H233.055V147.672H229.82ZM288.488 209.23H291.727V149.176H288.488ZM347.156 209.23H350.395V104.211H347.156ZM405.824 209.23H409.063V115.422H405.824Z' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M112.481 209.23H115.719V145.918H112.481ZM171.149 209.23H174.387V145.105H171.149ZM229.82 209.23H233.055V147.672H229.82ZM288.488 209.23H291.727V149.176H288.488ZM347.156 209.23H350.395V104.211H347.156ZM405.824 209.23H409.063V115.422H405.824Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M114.098 145.918V145.793' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M114.098 145.918V145.793' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M112.105 145.793H116.09' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M114.098 145.918V146.043' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M114.098 145.918V146.043' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M116.094 146.043H112.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M172.77 145.105V144.793' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M172.77 145.105V144.793' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M170.777 144.793H174.762' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M172.77 145.105V145.418' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M172.77 145.105V145.418' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M174.762 145.418H170.777' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M231.438 147.672V147.422' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M231.438 147.672V147.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M229.445 147.422H233.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M231.438 147.672V147.922' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M231.438 147.672V147.922' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M233.43 147.922H229.445' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.106 149.176V148.738' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M290.106 149.176V148.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M288.113 148.738H292.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.106 149.176V149.613' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M290.106 149.176V149.613' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M292.098 149.613H288.113' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M348.777 104.211V100.582' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M348.777 104.211V100.582' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M346.781 100.582H350.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M348.777 104.211V107.844' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M348.777 104.211V107.844' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M350.77 107.843H346.785' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M407.445 115.422V109.848' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M407.445 115.422V109.848' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M405.453 109.847H409.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M407.445 115.422V120.996' fill='#c96' clip-path='url(#clip1)'/>
+<path d='M407.445 115.422V120.996' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M409.437 120.996H405.453' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M117.711 209.23H120.949V143.226H117.711ZM176.379 209.23H179.617V132.266H176.379ZM235.051 209.23H238.285V132.644H235.051ZM293.719 209.23H296.957V110.539H293.719ZM352.387 209.23H355.625V83.984H352.387ZM411.055 209.23H414.293V83.984H411.055Z' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M117.711 209.23H120.949V143.226H117.711ZM176.379 209.23H179.617V132.266H176.379ZM235.051 209.23H238.285V132.644H235.051ZM293.719 209.23H296.957V110.539H293.719ZM352.387 209.23H355.625V83.984H352.387ZM411.055 209.23H414.293V83.984H411.055Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M119.328 143.226V142.914' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M119.328 143.226V142.914' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M117.336 142.914H121.321' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M119.328 143.226V143.539' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M119.328 143.226V143.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M121.325 143.539H117.34' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M178 132.266V131.641' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M178 132.266V131.641' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M176.008 131.64H179.993' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M178 132.266V132.894' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M178 132.266V132.894' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M179.993 132.895H176.008' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M236.668 132.644V132.078' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M236.668 132.644V132.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M234.676 132.079H238.661' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M236.668 132.644V133.207' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M236.668 132.644V133.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M238.66 133.207H234.675' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.336 110.539V109.785' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M295.336 110.539V109.785' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M293.344 109.785H297.329' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.336 110.539V111.289' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M295.336 110.539V111.289' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M297.328 111.289H293.343' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M354.008 83.984' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M352.012 83.984H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M354.008 83.984' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M352.012 83.984H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M412.676 83.984' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M410.684 83.984H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M412.676 83.984' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M410.684 83.984H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M122.941 209.23H126.18V136.59H122.941ZM181.609 209.23H184.848V120.242H181.609ZM240.281 209.23H243.516V140.785H240.281ZM298.949 209.23H302.188V83.984H298.949ZM357.617 209.23H360.856V87.117H357.617ZM416.285 209.23H419.524V83.984H416.285Z' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M122.941 209.23H126.18V136.59H122.941ZM181.609 209.23H184.848V120.242H181.609ZM240.281 209.23H243.516V140.785H240.281ZM298.949 209.23H302.188V83.984H298.949ZM357.617 209.23H360.856V87.117H357.617ZM416.285 209.23H419.524V83.984H416.285Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M124.559 136.59V136.465' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M124.559 136.59V136.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M122.566 136.465H126.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M124.559 136.59V136.715' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M124.559 136.59V136.715' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M126.555 136.715H122.57' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M183.231 120.242V119.305' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M183.231 120.242V119.305' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M181.238 119.304H185.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M183.231 120.242V121.184' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M183.231 120.242V121.184' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M185.223 121.183H181.238' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M241.899 140.785V140.41' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M241.899 140.785V140.41' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M239.906 140.41H243.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M241.899 140.785V141.16' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M241.899 140.785V141.16' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M243.891 141.16H239.906' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M300.567 83.984' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M298.574 83.984H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M300.567 83.984' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M298.574 83.984H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M359.238 87.117V85.363' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M359.238 87.117V85.363' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M357.242 85.363H361.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M359.238 87.117V88.871' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M359.238 87.117V88.871' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M361.231 88.871H357.246' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M417.906 83.984' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M415.914 83.984H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M417.906 83.984' fill='#bfbf80' clip-path='url(#clip1)'/>
+<path d='M415.914 83.984H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M128.172 209.23H131.41V141.285H128.172ZM186.84 209.23H190.078V131.266H186.84ZM245.512 209.23H248.746V139.781H245.512ZM304.18 209.23H307.418V99.328H304.18ZM362.848 209.23H366.086V105.34H362.848ZM421.516 209.23H424.754V83.984H421.516Z' fill='#399' clip-path='url(#clip1)'/>
+<path d='M128.172 209.23H131.41V141.285H128.172ZM186.84 209.23H190.078V131.266H186.84ZM245.512 209.23H248.746V139.781H245.512ZM304.18 209.23H307.418V99.328H304.18ZM362.848 209.23H366.086V105.34H362.848ZM421.516 209.23H424.754V83.984H421.516Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M129.789 141.285V141.098' fill='#399' clip-path='url(#clip1)'/>
+<path d='M129.789 141.285V141.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M127.797 141.097H131.782' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M129.789 141.285V141.473' fill='#399' clip-path='url(#clip1)'/>
+<path d='M129.789 141.285V141.473' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M131.785 141.473H127.8' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M188.461 131.266V130.891' fill='#399' clip-path='url(#clip1)'/>
+<path d='M188.461 131.266V130.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M186.469 130.891H190.454' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M188.461 131.266V131.641' fill='#399' clip-path='url(#clip1)'/>
+<path d='M188.461 131.266V131.641' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M190.453 131.64H186.468' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M247.129 139.781V139.594' fill='#399' clip-path='url(#clip1)'/>
+<path d='M247.129 139.781V139.594' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M245.137 139.593H249.122' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M247.129 139.781V139.969' fill='#399' clip-path='url(#clip1)'/>
+<path d='M247.129 139.781V139.969' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M249.121 139.969H245.136' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M305.797 99.328V98.828' fill='#399' clip-path='url(#clip1)'/>
+<path d='M305.797 99.328V98.828' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M303.804 98.828H307.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M305.797 99.328V99.828' fill='#399' clip-path='url(#clip1)'/>
+<path d='M305.797 99.328V99.828' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M307.789 99.828H303.804' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M364.469 105.34V103.586' fill='#399' clip-path='url(#clip1)'/>
+<path d='M364.469 105.34V103.586' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M362.473 103.586H366.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M364.469 105.34V107.094' fill='#399' clip-path='url(#clip1)'/>
+<path d='M364.469 105.34V107.094' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M366.461 107.094H362.476' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M423.137 83.984' fill='#399' clip-path='url(#clip1)'/>
+<path d='M421.144 83.984H425.128' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M423.137 83.984' fill='#399' clip-path='url(#clip1)'/>
+<path d='M421.144 83.984H425.128' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M133.402 209.23H136.641V138.656H133.402ZM192.07 209.23H195.309V138.531H192.07ZM250.742 209.23H253.977V143.914H250.742ZM309.41 209.23H312.649V123H309.41ZM368.078 209.23H371.317V141.285H368.078ZM426.746 209.23H429.984V83.984H426.746Z' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M133.402 209.23H136.641V138.656H133.402ZM192.07 209.23H195.309V138.531H192.07ZM250.742 209.23H253.977V143.914H250.742ZM309.41 209.23H312.649V123H309.41ZM368.078 209.23H371.317V141.285H368.078ZM426.746 209.23H429.984V83.984H426.746Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M135.02 138.656V138.531' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M135.02 138.656V138.531' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M133.027 138.531H137.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M135.02 138.656V138.781' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M135.02 138.656V138.781' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M137.016 138.781H133.031' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M193.692 138.531V138.215' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M193.692 138.531V138.215' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M191.699 138.215H195.684' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M193.692 138.531V138.844' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M193.692 138.531V138.844' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M195.684 138.844H191.699' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M252.359 143.914V143.539' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M252.359 143.914V143.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M250.367 143.539H254.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M252.359 143.914V144.293' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M252.359 143.914V144.293' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M254.352 144.293H250.367' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M311.027 123V122.75' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M311.027 123V122.75' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M309.035 122.75H313.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M311.027 123V123.25' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M311.027 123V123.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M313.02 123.25H309.035' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M369.699 141.285V140.41' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M369.699 141.285V140.41' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M367.703 140.41H371.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M369.699 141.285V142.16' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M369.699 141.285V142.16' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M371.692 142.16H367.707' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M428.367 83.984' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M426.375 83.984H430.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M428.367 83.984' fill='#d9b3b3' clip-path='url(#clip1)'/>
+<path d='M426.375 83.984H430.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<g transform='matrix(0 -1 1 0 -99.092 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.423 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.246 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 76.915 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.584 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.253 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -93.862 255.634)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.193 253.943)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.476 255.258)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.145 257.513)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.814 254.82)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.483 241.168)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -88.631 254.82)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.962 247.242)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.707 250.937)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.376 243.548)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.045 255.383)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.714 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-57'/>
+<use x='126.877' y='188.674' xlink:href='#g2-49'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.401 250.687)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.732 252.315)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.937 245.74)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.606 239.79)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.275 229.395)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-52'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.944 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-54'/>
+<use x='126.877' y='188.674' xlink:href='#g2-53'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.17 228.831)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-52'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.501 246.241)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.168 220.252)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.837 200.651)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-56'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.506 242.483)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.175 226.514)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-52'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -72.94 254.382)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.271 253.567)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.398 256.135)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.067 257.638)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.736 212.675)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-54'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.405 223.884)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -67.709 251.689)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.04 240.73)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.629 241.105)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.298 219)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.967 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-49'/>
+<use x='126.877' y='188.674' xlink:href='#g2-57'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.636 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-49'/>
+<use x='126.877' y='188.674' xlink:href='#g2-55'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.479 245.051)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.81 228.706)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-52'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.859 249.246)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.528 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-49'/>
+<use x='122.76' y='188.674' xlink:href='#g2-53'/>
+<use x='125.406' y='188.674' xlink:href='#g2-53'/>
+<use x='128.053' y='188.674' xlink:href='#g2-46'/>
+<use x='129.523' y='188.674' xlink:href='#g2-50'/>
+<use x='132.169' y='188.674' xlink:href='#g2-51'/>
+<use x='134.816' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.197 195.579)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.866 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-55'/>
+<use x='126.877' y='188.674' xlink:href='#g2-57'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.249 249.747)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.42 239.728)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.089 248.244)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.758 207.79)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-55'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.427 213.802)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-54'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 236.096 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-51'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-48'/>
+<use x='126.877' y='188.674' xlink:href='#g2-57'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.018 247.117)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.651 246.992)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 65.32 252.378)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.989 231.462)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.658 249.747)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 241.327 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-48'/>
+<use x='126.877' y='188.674' xlink:href='#g2-51'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -129.314 316.355)'>
+<use x='114.487' y='188.674' xlink:href='#g1-82'/>
+<use x='120.457' y='188.674' xlink:href='#g1-101'/>
+<use x='124.553' y='188.674' xlink:href='#g1-108'/>
+<use x='126.753' y='188.674' xlink:href='#g1-97'/>
+<use x='131.181' y='188.674' xlink:href='#g1-116'/>
+<use x='134.509' y='188.674' xlink:href='#g1-105'/>
+<use x='136.709' y='188.674' xlink:href='#g1-118'/>
+<use x='140.957' y='188.674' xlink:href='#g1-101'/>
+<use x='148.124' y='188.674' xlink:href='#g1-116'/>
+<use x='151.452' y='188.674' xlink:href='#g1-105'/>
+<use x='153.652' y='188.674' xlink:href='#g1-109'/>
+<use x='160.972' y='188.674' xlink:href='#g1-101'/>
+<use x='168.139' y='188.674' xlink:href='#g3-40'/>
+<use x='171.432' y='188.674' xlink:href='#g3-108'/>
+<use x='173.453' y='188.674' xlink:href='#g3-111'/>
+<use x='177.452' y='188.674' xlink:href='#g3-119'/>
+<use x='183' y='188.674' xlink:href='#g3-101'/>
+<use x='186.764' y='188.674' xlink:href='#g3-114'/>
+<use x='192.479' y='188.674' xlink:href='#g3-105'/>
+<use x='194.499' y='188.674' xlink:href='#g3-115'/>
+<use x='200.568' y='188.674' xlink:href='#g3-98'/>
+<use x='205.176' y='188.674' xlink:href='#g3-101'/>
+<use x='208.94' y='188.674' xlink:href='#g3-116'/>
+<use x='211.998' y='188.674' xlink:href='#g3-116'/>
+<use x='215.056' y='188.674' xlink:href='#g3-101'/>
+<use x='218.819' y='188.674' xlink:href='#g3-114'/>
+<use x='221.711' y='188.674' xlink:href='#g3-41'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg b/extlib/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg
new file mode 100644 (file)
index 0000000..c748877
--- /dev/null
@@ -0,0 +1,1255 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.628pt' height='255.741pt' viewBox='106.732 54.993 381.628 255.741'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip2'>
+<path d='M135.949 249.281H487.961V81.519H135.949Z'/>
+</clipPath>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-45' xlink:href='#g0-45' transform='scale(1.143)'/>
+<use id='g3-49' xlink:href='#g0-49' transform='scale(1.143)'/>
+<use id='g3-54' xlink:href='#g0-54' transform='scale(1.143)'/>
+<use id='g3-56' xlink:href='#g0-56' transform='scale(1.143)'/>
+<use id='g3-58' xlink:href='#g0-58' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-103' xlink:href='#g0-103' transform='scale(1.143)'/>
+<use id='g3-104' xlink:href='#g0-104' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-106' xlink:href='#g0-106' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g3-120' xlink:href='#g0-120' transform='scale(1.143)'/>
+<use id='g2-44' xlink:href='#g0-44' transform='scale(.714)'/>
+<use id='g2-45' xlink:href='#g0-45' transform='scale(.714)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-64' xlink:href='#g0-64' transform='scale(.714)'/>
+<use id='g2-65' xlink:href='#g0-65' transform='scale(.714)'/>
+<use id='g2-67' xlink:href='#g0-67' transform='scale(.714)'/>
+<use id='g2-68' xlink:href='#g0-68' transform='scale(.714)'/>
+<use id='g2-71' xlink:href='#g0-71' transform='scale(.714)'/>
+<use id='g2-77' xlink:href='#g0-77' transform='scale(.714)'/>
+<use id='g2-85' xlink:href='#g0-85' transform='scale(.714)'/>
+<use id='g2-97' xlink:href='#g0-97' transform='scale(.714)'/>
+<use id='g2-98' xlink:href='#g0-98' transform='scale(.714)'/>
+<use id='g2-99' xlink:href='#g0-99' transform='scale(.714)'/>
+<use id='g2-100' xlink:href='#g0-100' transform='scale(.714)'/>
+<use id='g2-101' xlink:href='#g0-101' transform='scale(.714)'/>
+<use id='g2-103' xlink:href='#g0-103' transform='scale(.714)'/>
+<use id='g2-104' xlink:href='#g0-104' transform='scale(.714)'/>
+<use id='g2-105' xlink:href='#g0-105' transform='scale(.714)'/>
+<use id='g2-108' xlink:href='#g0-108' transform='scale(.714)'/>
+<use id='g2-109' xlink:href='#g0-109' transform='scale(.714)'/>
+<use id='g2-110' xlink:href='#g0-110' transform='scale(.714)'/>
+<use id='g2-111' xlink:href='#g0-111' transform='scale(.714)'/>
+<use id='g2-114' xlink:href='#g0-114' transform='scale(.714)'/>
+<use id='g2-115' xlink:href='#g0-115' transform='scale(.714)'/>
+<use id='g2-116' xlink:href='#g0-116' transform='scale(.714)'/>
+<use id='g2-117' xlink:href='#g0-117' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<use id='g2-122' xlink:href='#g0-122' transform='scale(.714)'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-109' d='M6.581-2.663C6.581-3.327 6.402-4.08 5.317-4.08C4.564-4.08 4.142-3.622 3.927-3.344C3.865-3.524 3.676-4.08 2.762-4.08C2.053-4.08 1.623-3.667 1.417-3.398V-4.035H.726V0H1.47V-2.188C1.47-2.78 1.704-3.497 2.385-3.497C3.282-3.497 3.282-2.86 3.282-2.6V0H4.026V-2.188C4.026-2.78 4.259-3.497 4.94-3.497C5.837-3.497 5.837-2.86 5.837-2.6V0H6.581V-2.663Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-44' d='M1.339-.007V-.628H.711V0H.907L.704 .893H1.018L1.339-.007Z'/>
+<path id='g0-45' d='M2.05-1.332V-1.771H.084V-1.332H2.05Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-58' d='M1.339-3.096H.711V-2.469H1.339V-3.096ZM.711-.628V0H1.339V-.628H.711Z'/>
+<path id='g0-64' d='M4.142-.614C4.038-.614 4.024-.614 3.968-.586C3.626-.467 3.271-.391 2.901-.391C1.778-.391 .976-1.339 .976-2.42C.976-3.592 1.883-4.449 2.859-4.449C3.055-4.449 3.515-4.4 3.745-3.843C3.55-3.954 3.333-4.003 3.152-4.003C2.406-4.003 1.778-3.306 1.778-2.42C1.778-1.513 2.427-.837 3.145-.837C3.689-.837 4.519-1.276 4.519-2.518C4.519-3.222 4.47-4.91 2.866-4.91C1.541-4.91 .411-3.815 .411-2.42C.411-1.039 1.527 .07 2.873 .07C3.515 .07 4.115-.195 4.519-.614H4.142ZM3.152-1.297C2.72-1.297 2.343-1.778 2.343-2.42C2.343-3.082 2.734-3.543 3.145-3.543C3.578-3.543 3.954-3.062 3.954-2.42C3.954-1.757 3.564-1.297 3.152-1.297Z'/>
+<path id='g0-65' d='M2.803-4.84H2.127L.209 0H.781L1.325-1.381H3.445L3.989 0H4.721L2.803-4.84ZM2.392-4.31L3.271-1.792H1.499L2.392-4.31Z'/>
+<path id='g0-67' d='M4.317-.851C3.829-.551 3.605-.418 2.908-.418C1.827-.418 1.172-1.43 1.172-2.434C1.172-3.466 1.89-4.435 2.908-4.435C3.368-4.435 3.843-4.289 4.163-4.045L4.275-4.679C3.787-4.861 3.396-4.917 2.887-4.917C1.506-4.917 .474-3.773 .474-2.427C.474-.99 1.569 .07 2.929 .07C3.612 .07 3.898-.07 4.359-.321L4.317-.851Z'/>
+<path id='g0-68' d='M.683-4.84V0H2.664C3.919 0 4.931-1.06 4.931-2.378C4.931-3.745 3.912-4.84 2.664-4.84H.683ZM1.367-.411V-4.428H2.476C3.431-4.428 4.247-3.668 4.247-2.385C4.247-1.088 3.396-.411 2.476-.411H1.367Z'/>
+<path id='g0-71' d='M4.442-2.085H2.88V-1.625H3.829V-.558C3.522-.481 3.222-.418 2.908-.418C1.834-.418 1.172-1.43 1.172-2.427C1.172-3.382 1.82-4.435 2.873-4.435C3.515-4.435 3.919-4.24 4.268-3.947L4.38-4.582C3.898-4.812 3.473-4.924 2.943-4.924C1.534-4.924 .474-3.822 .474-2.427C.474-1.067 1.527 .07 2.901 .07C3.403 .07 3.996-.042 4.442-.272V-2.085Z'/>
+<path id='g0-77' d='M3.884-2.42C3.801-2.211 3.299-.983 3.229-.69H3.222C3.173-.893 2.852-1.695 2.783-1.876L1.583-4.84H.732V0H1.318V-4.282H1.325C1.381-4.038 1.743-3.117 1.778-3.041L2.943-.146H3.494L4.533-2.713C4.533-2.72 5.014-3.905 5.133-4.289H5.14V0H5.726V-4.84H4.868L3.884-2.42Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-85' d='M4.4-4.84H3.794V-1.625C3.794-.69 3.166-.265 2.566-.265S1.381-.697 1.381-1.618V-4.84H.676V-1.632C.676-.607 1.555 .146 2.559 .146C3.557 .146 4.4-.614 4.4-1.632V-4.84Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-103' d='M3.508-3.166C3.354-3.166 2.887-3.159 2.357-2.957L2.343-2.95C2.092-3.117 1.848-3.166 1.646-3.166C.962-3.166 .453-2.629 .453-2.029C.453-1.785 .537-1.534 .697-1.339C.6-1.22 .495-1.025 .495-.76C.495-.488 .607-.314 .669-.23C.286-.007 .209 .314 .209 .481C.209 1.011 .941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 .481C3.487-.502 2.267-.502 1.967-.502H1.318C1.206-.502 .907-.502 .907-.865C.907-1.004 .955-1.074 .962-1.088C1.206-.934 1.451-.886 1.639-.886C2.322-.886 2.831-1.423 2.831-2.022C2.831-2.246 2.769-2.448 2.643-2.636C2.615-2.678 2.615-2.685 2.615-2.692C2.615-2.72 3.034-2.72 3.068-2.72C3.075-2.72 3.34-2.72 3.592-2.692L3.508-3.166ZM1.646-1.318C1.269-1.318 .99-1.555 .99-2.022C.99-2.566 1.339-2.734 1.639-2.734C2.015-2.734 2.294-2.497 2.294-2.029C2.294-1.485 1.946-1.318 1.646-1.318ZM1.974 .042C2.134 .042 2.957 .042 2.957 .488C2.957 .788 2.434 .997 1.848 .997S.739 .788 .739 .488C.739 .453 .739 .042 1.304 .042H1.974Z'/>
+<path id='g0-104' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.625-3.166 1.304-2.817 1.165-2.671V-4.84H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-106' d='M1.381-4.784H.676V-4.08H1.381V-4.784ZM-.453 1.186C-.133 1.36 .181 1.423 .446 1.423C.928 1.423 1.381 1.053 1.381 .411V-3.096H.795V.46C.795 .586 .795 .697 .649 .816C.488 .934 .293 .934 .23 .934C-.063 .934-.244 .802-.328 .725L-.453 1.186Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-117' d='M3.243-3.096H2.636V-1.074C2.636-.516 2.162-.342 1.757-.342C1.241-.342 1.186-.481 1.186-.802V-3.096H.579V-.76C.579-.139 .851 .07 1.339 .07C1.625 .07 2.239 .014 2.657-.321V0H3.243V-3.096Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+<path id='g0-122' d='M2.957-2.803V-3.096H.307V-2.65H1.332C1.416-2.65 1.499-2.657 1.583-2.657H2.127L.209-.307V0H2.978V-.467H1.897C1.813-.467 1.73-.46 1.646-.46H1.039L2.957-2.803Z'/>
+</defs>
+<g id='page2'>
+<path d='M194.617 258.141V249.281M253.285 258.141V249.281M311.953 258.141V249.281M370.625 258.141V249.281M429.293 258.141V249.281M194.617 72.66V81.519M253.285 72.66V81.519M311.953 72.66V81.519M370.625 72.66V81.519M429.293 72.66V81.519' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M165.281 253.535V249.281M223.953 253.535V249.281M282.621 253.535V249.281M341.289 253.535V249.281M399.957 253.535V249.281M458.629 253.535V249.281M165.281 77.266V81.519M223.953 77.266V81.519M282.621 77.266V81.519M341.289 77.266V81.519M399.957 77.266V81.519M458.629 77.266V81.519' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 249.281H140.199M135.949 215.73H140.199M135.949 182.176H140.199M135.949 148.625H140.199M135.949 115.07H140.199M135.949 81.519H140.199M487.961 249.281H483.711M487.961 215.73H483.711M487.961 182.176H483.711M487.961 148.625H483.711M487.961 115.07H483.711M487.961 81.519H483.711' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 249.281V81.519H487.961V249.281H135.949Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-97'/>
+<use x='172.353' y='188.688' xlink:href='#g3-108'/>
+<use x='174.373' y='188.688' xlink:href='#g3-108'/>
+<use x='176.393' y='188.688' xlink:href='#g3-111'/>
+<use x='180.863' y='188.688' xlink:href='#g3-99'/>
+<use x='184.627' y='188.688' xlink:href='#g3-45'/>
+<use x='187.449' y='188.688' xlink:href='#g3-116'/>
+<use x='190.507' y='188.688' xlink:href='#g3-101'/>
+<use x='194.271' y='188.688' xlink:href='#g3-115'/>
+<use x='197.517' y='188.688' xlink:href='#g3-116'/>
+<use x='200.575' y='188.688' xlink:href='#g3-49'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-97'/>
+<use x='172.353' y='188.688' xlink:href='#g3-108'/>
+<use x='174.373' y='188.688' xlink:href='#g3-108'/>
+<use x='176.393' y='188.688' xlink:href='#g3-111'/>
+<use x='180.863' y='188.688' xlink:href='#g3-99'/>
+<use x='184.627' y='188.688' xlink:href='#g3-45'/>
+<use x='187.449' y='188.688' xlink:href='#g3-116'/>
+<use x='190.507' y='188.688' xlink:href='#g3-101'/>
+<use x='194.271' y='188.688' xlink:href='#g3-115'/>
+<use x='197.517' y='188.688' xlink:href='#g3-116'/>
+<use x='200.575' y='188.688' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-115'/>
+<use x='171.531' y='188.688' xlink:href='#g3-104'/>
+<use x='175.904' y='188.688' xlink:href='#g3-54'/>
+<use x='180.138' y='188.688' xlink:href='#g3-98'/>
+<use x='184.746' y='188.688' xlink:href='#g3-101'/>
+<use x='188.509' y='188.688' xlink:href='#g3-110'/>
+<use x='192.882' y='188.688' xlink:href='#g3-99'/>
+<use x='196.646' y='188.688' xlink:href='#g3-104'/>
+<use x='201.018' y='188.688' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-115'/>
+<use x='171.531' y='188.688' xlink:href='#g3-104'/>
+<use x='175.904' y='188.688' xlink:href='#g3-56'/>
+<use x='180.138' y='188.688' xlink:href='#g3-98'/>
+<use x='184.746' y='188.688' xlink:href='#g3-101'/>
+<use x='188.509' y='188.688' xlink:href='#g3-110'/>
+<use x='192.882' y='188.688' xlink:href='#g3-99'/>
+<use x='196.646' y='188.688' xlink:href='#g3-104'/>
+<use x='201.018' y='188.688' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-120'/>
+<use x='172.187' y='188.688' xlink:href='#g3-109'/>
+<use x='178.912' y='188.688' xlink:href='#g3-97'/>
+<use x='182.98' y='188.688' xlink:href='#g3-108'/>
+<use x='185' y='188.688' xlink:href='#g3-108'/>
+<use x='187.02' y='188.688' xlink:href='#g3-111'/>
+<use x='191.49' y='188.688' xlink:href='#g3-99'/>
+<use x='195.254' y='188.688' xlink:href='#g3-45'/>
+<use x='198.076' y='188.688' xlink:href='#g3-116'/>
+<use x='201.134' y='188.688' xlink:href='#g3-101'/>
+<use x='204.898' y='188.688' xlink:href='#g3-115'/>
+<use x='208.144' y='188.688' xlink:href='#g3-116'/>
+<use x='211.202' y='188.688' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' y='188.688' xlink:href='#g3-99'/>
+<use x='172.049' y='188.688' xlink:href='#g3-97'/>
+<use x='176.117' y='188.688' xlink:href='#g3-99'/>
+<use x='179.88' y='188.688' xlink:href='#g3-104'/>
+<use x='184.253' y='188.688' xlink:href='#g3-101'/>
+<use x='188.017' y='188.688' xlink:href='#g3-45'/>
+<use x='190.839' y='188.688' xlink:href='#g3-115'/>
+<use x='194.086' y='188.688' xlink:href='#g3-99'/>
+<use x='197.849' y='188.688' xlink:href='#g3-114'/>
+<use x='200.741' y='188.688' xlink:href='#g3-97'/>
+<use x='204.81' y='188.688' xlink:href='#g3-116'/>
+<use x='207.868' y='188.688' xlink:href='#g3-99'/>
+<use x='211.631' y='188.688' xlink:href='#g3-104'/>
+<use x='216.004' y='188.688' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' y='188.688' xlink:href='#g2-50'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' y='188.688' xlink:href='#g2-50'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-120'/>
+</g>
+<path d='M135.949 182.176H487.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M140.125 249.281H143.363V182.176H140.125ZM198.797 249.281H202.035V182.176H198.797ZM257.465 249.281H260.703V182.176H257.465ZM316.133 249.281H319.371V182.176H316.133ZM374.801 249.281H378.039V182.176H374.801ZM433.473 249.281H436.711V182.176H433.473Z' fill='#933' clip-path='url(#clip2)'/>
+<path d='M140.125 249.281H143.363V182.176H140.125ZM198.797 249.281H202.035V182.176H198.797ZM257.465 249.281H260.703V182.176H257.465ZM316.133 249.281H319.371V182.176H316.133ZM374.801 249.281H378.039V182.176H374.801ZM433.473 249.281H436.711V182.176H433.473Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M141.746 182.176V181.773' fill='#933' clip-path='url(#clip2)'/>
+<path d='M141.746 182.176V181.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M139.754 181.773H143.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M141.746 182.176V182.578' fill='#933' clip-path='url(#clip2)'/>
+<path d='M141.746 182.176V182.578' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M143.738 182.578H139.754' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M200.414 182.176V181.508' fill='#933' clip-path='url(#clip2)'/>
+<path d='M200.414 182.176V181.508' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M198.422 181.508H202.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M200.414 182.176V182.848' fill='#933' clip-path='url(#clip2)'/>
+<path d='M200.414 182.176V182.848' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M202.406 182.848H198.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M259.082 182.176' fill='#933' clip-path='url(#clip2)'/>
+<path d='M257.09 182.176H261.074' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M259.082 182.176' fill='#933' clip-path='url(#clip2)'/>
+<path d='M257.09 182.176H261.074' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M317.754 182.176V179.695' fill='#933' clip-path='url(#clip2)'/>
+<path d='M317.754 182.176V179.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M315.758 179.695H319.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M317.754 182.176V184.66' fill='#933' clip-path='url(#clip2)'/>
+<path d='M317.754 182.176V184.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M319.746 184.66H315.762' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M376.422 182.176V180.363' fill='#933' clip-path='url(#clip2)'/>
+<path d='M376.422 182.176V180.363' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M374.43 180.363H378.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M376.422 182.176V183.988' fill='#933' clip-path='url(#clip2)'/>
+<path d='M376.422 182.176V183.988' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M378.414 183.988H374.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M435.09 182.176V179.629' fill='#933' clip-path='url(#clip2)'/>
+<path d='M435.09 182.176V179.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M433.098 179.629H437.082' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M435.09 182.176V184.727' fill='#933' clip-path='url(#clip2)'/>
+<path d='M435.09 182.176V184.727' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M437.082 184.727H433.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M145.356 249.281H148.594V182.312H145.356ZM204.028 249.281H207.266V182.648H204.028ZM262.695 249.281H265.934V167.816H262.695ZM321.363 249.281H324.602V183.922H321.363ZM380.031 249.281H383.27V176.605H380.031ZM438.703 249.281H441.942V180.699H438.703Z' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M145.356 249.281H148.594V182.312H145.356ZM204.028 249.281H207.266V182.648H204.028ZM262.695 249.281H265.934V167.816H262.695ZM321.363 249.281H324.602V183.922H321.363ZM380.031 249.281H383.27V176.605H380.031ZM438.703 249.281H441.942V180.699H438.703Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M146.977 182.312V182.043' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M146.977 182.312V182.043' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M144.984 182.043H148.968' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M146.977 182.312V182.578' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M146.977 182.312V182.578' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M148.968 182.578H144.984' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M205.645 182.648V182.379' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M205.645 182.648V182.379' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M203.652 182.379H207.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M205.645 182.648V182.914' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M205.645 182.648V182.914' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M207.636 182.914H203.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M264.313 167.816V163.051' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M264.313 167.816V163.051' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M262.32 163.051H266.304' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M264.313 167.816V172.582' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M264.313 167.816V172.582' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M266.308 172.582H262.32' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M322.984 183.922V182.176' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M322.984 183.922V182.176' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M320.988 182.176H324.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M322.984 183.922V185.668' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M322.984 183.922V185.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M324.976 185.668H320.992' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M381.652 176.605V172.18' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M381.652 176.605V172.18' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M379.66 172.179H383.644' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M381.652 176.605V181.035' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M381.652 176.605V181.035' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M383.644 181.035H379.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M440.32 180.699V177.746' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M440.32 180.699V177.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M438.328 177.746H442.312' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M440.32 180.699V183.652' fill='#bf8080' clip-path='url(#clip2)'/>
+<path d='M440.32 180.699V183.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M442.312 183.652H438.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M150.586 249.281H153.824V181.707H150.586ZM209.258 249.281H212.496V180.969H209.258ZM267.926 249.281H271.164V143.859H267.926ZM326.594 249.281H329.832V81.519H326.594ZM385.262 249.281H388.5V81.519H385.262ZM443.934 249.281H447.172V81.519H443.934Z' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M150.586 249.281H153.824V181.707H150.586ZM209.258 249.281H212.496V180.969H209.258ZM267.926 249.281H271.164V143.859H267.926ZM326.594 249.281H329.832V81.519H326.594ZM385.262 249.281H388.5V81.519H385.262ZM443.934 249.281H447.172V81.519H443.934Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M152.207 181.707V181.172' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M152.207 181.707V181.172' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M150.215 181.171H154.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M152.207 181.707V182.242' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M152.207 181.707V182.242' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M154.2 182.242H150.215' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M210.875 180.969V179.359' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M210.875 180.969V179.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M208.883 179.36H212.867' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M210.875 180.969V182.578' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M210.875 180.969V182.578' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M212.868 182.578H208.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M269.543 143.859V132.117' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M269.543 143.859V132.117' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M267.551 132.117H271.535' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M269.543 143.859V155.602' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M269.543 143.859V155.602' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M271.539 155.602H267.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M328.215 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M326.219 81.52H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M328.215 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M326.219 81.52H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M386.883 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M384.891 81.52H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M386.883 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M384.891 81.52H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M445.551 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M443.559 81.52H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M445.551 81.519' fill='#8080bf' clip-path='url(#clip2)'/>
+<path d='M443.559 81.52H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M155.817 249.281H159.055V176.273H155.817ZM214.488 249.281H217.727V173.988H214.488ZM273.156 249.281H276.395V81.519H273.156ZM331.824 249.281H335.063V81.519H331.824ZM390.492 249.281H393.731V81.519H390.492ZM449.164 249.281H452.402V81.519H449.164Z' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M155.817 249.281H159.055V176.273H155.817ZM214.488 249.281H217.727V173.988H214.488ZM273.156 249.281H276.395V81.519H273.156ZM331.824 249.281H335.063V81.519H331.824ZM390.492 249.281H393.731V81.519H390.492ZM449.164 249.281H452.402V81.519H449.164Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M157.438 176.273V176.137' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M157.438 176.273V176.137' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M155.445 176.136H159.429' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M157.438 176.273V176.406' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M157.438 176.273V176.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M159.43 176.406H155.445' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M216.106 173.988V172.715' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M216.106 173.988V172.715' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M214.113 172.715H218.097' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M216.106 173.988V175.266' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M216.106 173.988V175.266' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M218.098 175.266H214.113' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M274.774 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M272.781 81.52H276.765' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M274.774 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M272.781 81.52H276.765' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M333.445 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M331.449 81.52H335.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M333.445 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M331.449 81.52H335.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M392.113 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M390.121 81.52H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M392.113 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M390.121 81.52H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M450.781 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M448.789 81.52H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M450.781 81.519' fill='#ffb733' clip-path='url(#clip2)'/>
+<path d='M448.789 81.52H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M161.047 249.281H164.285V157.48H161.047ZM219.719 249.281H222.957V147.215H219.719ZM278.387 249.281H281.625V81.519H278.387ZM337.055 249.281H340.293V81.519H337.055ZM395.723 249.281H398.961V166.406H395.723ZM454.395 249.281H457.633V182.176H454.395Z' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M161.047 249.281H164.285V157.48H161.047ZM219.719 249.281H222.957V147.215H219.719ZM278.387 249.281H281.625V81.519H278.387ZM337.055 249.281H340.293V81.519H337.055ZM395.723 249.281H398.961V166.406H395.723ZM454.395 249.281H457.633V182.176H454.395Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M162.668 157.48V157.012' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M162.668 157.48V157.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M160.676 157.011H164.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M162.668 157.48V157.953' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M162.668 157.48V157.953' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M164.661 157.953H160.676' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M221.336 147.215V146.812' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M221.336 147.215V146.812' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M219.344 146.812H223.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M221.336 147.215V147.617' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M221.336 147.215V147.617' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M223.329 147.617H219.344' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M280.004 81.519' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M278.012 81.52H281.996' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M280.004 81.519' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M278.012 81.52H281.996' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M338.676 81.519' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M336.68 81.52H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M338.676 81.519' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M336.68 81.52H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M397.344 166.406V166.273' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M397.344 166.406V166.273' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M395.352 166.274H399.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M397.344 166.406V166.543' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M397.344 166.406V166.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M399.336 166.543H395.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M456.012 182.176V179.629' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M456.012 182.176V179.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M454.02 179.629H458.004' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M456.012 182.176V184.727' fill='#bf80bf' clip-path='url(#clip2)'/>
+<path d='M456.012 182.176V184.727' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M458.004 184.727H454.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M166.278 249.281H169.516V167.949H166.278ZM224.949 249.281H228.188V176.137H224.949ZM283.617 249.281H286.856V110.305H283.617ZM342.285 249.281H345.524V157.48H342.285ZM400.953 249.281H404.192V186.473H400.953ZM459.625 249.281H462.863V183.652H459.625Z' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M166.278 249.281H169.516V167.949H166.278ZM224.949 249.281H228.188V176.137H224.949ZM283.617 249.281H286.856V110.305H283.617ZM342.285 249.281H345.524V157.48H342.285ZM400.953 249.281H404.192V186.473H400.953ZM459.625 249.281H462.863V183.652H459.625Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M167.899 167.949V167.816' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M167.899 167.949V167.816' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M165.906 167.816H169.89' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M167.899 167.949V168.086' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M167.899 167.949V168.086' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M169.891 168.086H165.906' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M226.567 176.137V175.199' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M226.567 176.137V175.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M224.574 175.199H228.558' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M226.567 176.137V177.078' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M226.567 176.137V177.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M228.559 177.078H224.574' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M285.234 110.305V105.543' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M285.234 110.305V105.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M283.242 105.543H287.226' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M285.234 110.305V115.07' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M285.234 110.305V115.07' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M287.23 115.07H283.242' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M343.906 157.48V153.187' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M343.906 157.48V153.187' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M341.91 153.187H345.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M343.906 157.48V161.777' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M343.906 157.48V161.777' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M345.898 161.778H341.914' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M402.574 186.473V186.269' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M402.574 186.473V186.269' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M400.582 186.27H404.566' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M402.574 186.473V186.672' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M402.574 186.473V186.672' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M404.566 186.672H400.582' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M461.242 183.652' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M459.25 183.652H463.234' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M461.242 183.652' fill='#c96' clip-path='url(#clip2)'/>
+<path d='M459.25 183.652H463.234' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M171.508 249.281H174.746V173.789H171.508ZM230.18 249.281H233.414V173.789H230.18ZM288.848 249.281H292.086V81.519H288.848ZM347.516 249.281H350.754V81.519H347.516ZM406.184 249.281H409.422V81.519H406.184ZM464.856 249.281H468.094V81.519H464.856Z' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M171.508 249.281H174.746V173.789H171.508ZM230.18 249.281H233.414V173.789H230.18ZM288.848 249.281H292.086V81.519H288.848ZM347.516 249.281H350.754V81.519H347.516ZM406.184 249.281H409.422V81.519H406.184ZM464.856 249.281H468.094V81.519H464.856Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M173.129 173.789V173.184' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M173.129 173.789V173.184' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M171.137 173.184H175.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M173.129 173.789V174.394' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M173.129 173.789V174.394' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M175.122 174.395H171.137' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M231.797 173.789V173.32' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M231.797 173.789V173.32' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M229.805 173.32H233.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M231.797 173.789V174.258' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M231.797 173.789V174.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M233.79 174.258H229.805' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M290.465 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M288.473 81.52H292.457' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M290.465 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M288.473 81.52H292.457' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M349.137 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M347.141 81.52H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M349.137 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M347.141 81.52H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M407.805 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M405.813 81.52H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M407.805 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M405.813 81.52H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M466.473 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M464.481 81.52H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M466.473 81.519' fill='#80bf80' clip-path='url(#clip2)'/>
+<path d='M464.481 81.52H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M176.738 249.281H179.977V144.664H176.738ZM235.41 249.281H238.645V178.016H235.41ZM294.078 249.281H297.317V81.519H294.078ZM352.746 249.281H355.984V81.519H352.746ZM411.414 249.281H414.652V81.519H411.414ZM470.086 249.281H473.324V183.652H470.086Z' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M176.738 249.281H179.977V144.664H176.738ZM235.41 249.281H238.645V178.016H235.41ZM294.078 249.281H297.317V81.519H294.078ZM352.746 249.281H355.984V81.519H352.746ZM411.414 249.281H414.652V81.519H411.414ZM470.086 249.281H473.324V183.652H470.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M178.36 144.664V142.922' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M178.36 144.664V142.922' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M176.367 142.922H180.351' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M178.36 144.664V146.41' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M178.36 144.664V146.41' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M180.352 146.41H176.367' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M237.027 178.016V177.344' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M237.027 178.016V177.344' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M235.035 177.343H239.019' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M237.027 178.016V178.687' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M237.027 178.016V178.687' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M239.02 178.688H235.035' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M295.695 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M293.703 81.52H297.687' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M295.695 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M293.703 81.52H297.687' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M354.367 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M352.371 81.52H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M354.367 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M352.371 81.52H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M413.035 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M411.043 81.52H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M413.035 81.519' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M411.043 81.52H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M471.703 183.652' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M469.711 183.652H473.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M471.703 183.652' fill='#bfbf80' clip-path='url(#clip2)'/>
+<path d='M469.711 183.652H473.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M181.969 249.281H185.207V165.199H181.969ZM240.641 249.281H243.875V163.387H240.641ZM299.309 249.281H302.547V81.519H299.309ZM357.977 249.281H361.215V81.519H357.977ZM416.645 249.281H419.883V116.613H416.645ZM475.317 249.281H478.555V81.519H475.317Z' fill='#399' clip-path='url(#clip2)'/>
+<path d='M181.969 249.281H185.207V165.199H181.969ZM240.641 249.281H243.875V163.387H240.641ZM299.309 249.281H302.547V81.519H299.309ZM357.977 249.281H361.215V81.519H357.977ZM416.645 249.281H419.883V116.613H416.645ZM475.317 249.281H478.555V81.519H475.317Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M183.59 165.199V164.664' fill='#399' clip-path='url(#clip2)'/>
+<path d='M183.59 165.199V164.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M181.598 164.664H185.583' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M183.59 165.199V165.734' fill='#399' clip-path='url(#clip2)'/>
+<path d='M183.59 165.199V165.734' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M185.582 165.734H181.597' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M242.258 163.387V162.852' fill='#399' clip-path='url(#clip2)'/>
+<path d='M242.258 163.387V162.852' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M240.266 162.851H244.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M242.258 163.387V163.926' fill='#399' clip-path='url(#clip2)'/>
+<path d='M242.258 163.387V163.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M244.25 163.926H240.265' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M300.926 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M298.933 81.52H302.917' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M300.926 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M298.933 81.52H302.917' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M359.598 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M357.602 81.52H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M359.598 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M357.602 81.52H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M418.266 116.613V116.211' fill='#399' clip-path='url(#clip2)'/>
+<path d='M418.266 116.613V116.211' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M416.274 116.211H420.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M418.266 116.613V117.016' fill='#399' clip-path='url(#clip2)'/>
+<path d='M418.266 116.613V117.016' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M420.257 117.016H416.273' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M476.934 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M474.942 81.52H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M476.934 81.519' fill='#399' clip-path='url(#clip2)'/>
+<path d='M474.942 81.52H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M187.199 249.281H190.438V175.133H187.199ZM245.871 249.281H249.106V171.574H245.871ZM304.539 249.281H307.777V81.519H304.539ZM363.207 249.281H366.445V81.519H363.207ZM421.875 249.281H425.113V170.836H421.875ZM480.547 249.281H483.785V171.707H480.547Z' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M187.199 249.281H190.438V175.133H187.199ZM245.871 249.281H249.106V171.574H245.871ZM304.539 249.281H307.777V81.519H304.539ZM363.207 249.281H366.445V81.519H363.207ZM421.875 249.281H425.113V170.836H421.875ZM480.547 249.281H483.785V171.707H480.547Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M188.82 175.133V174.797' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M188.82 175.133V174.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M186.828 174.797H190.813' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M188.82 175.133V175.465' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M188.82 175.133V175.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M190.813 175.464H186.828' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M247.488 171.574V171.238' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M247.488 171.574V171.238' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M245.496 171.239H249.48' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M247.488 171.574V171.91' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M247.488 171.574V171.91' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M249.481 171.91H245.496' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M306.156 81.519' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M304.164 81.52H308.148' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M306.156 81.519' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M304.164 81.52H308.148' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M364.828 81.519' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M362.832 81.52H366.82' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M364.828 81.519' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M362.832 81.52H366.82' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M423.496 170.836V169.629' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M423.496 170.836V169.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M421.504 169.629H425.488' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M423.496 170.836V172.043' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M423.496 170.836V172.043' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M425.488 172.043H421.504' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M482.164 171.707' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M480.172 171.707H484.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M482.164 171.707' fill='#d9b3b3' clip-path='url(#clip2)'/>
+<path d='M480.172 171.707H484.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M415.914 310.336H487.762V276.324H415.914Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<g transform='matrix(1 0 0 1 250.949 118.327)'>
+<use x='168.285' y='164.777' xlink:href='#g2-97'/>
+<use x='170.827' y='164.777' xlink:href='#g2-109'/>
+<use x='175.03' y='164.777' xlink:href='#g2-100'/>
+<use x='177.763' y='164.777' xlink:href='#g2-53'/>
+<use x='180.41' y='164.777' xlink:href='#g2-57'/>
+<use x='183.056' y='164.777' xlink:href='#g2-53'/>
+<use x='185.702' y='164.777' xlink:href='#g2-48'/>
+<use x='188.349' y='164.777' xlink:href='#g2-120'/>
+<use x='190.788' y='164.777' xlink:href='#g2-44'/>
+<use x='194.022' y='164.777' xlink:href='#g2-51'/>
+<use x='196.668' y='164.777' xlink:href='#g2-50'/>
+<use x='199.315' y='164.777' xlink:href='#g2-71'/>
+<use x='202.843' y='164.777' xlink:href='#g2-98'/>
+<use x='207.34' y='164.777' xlink:href='#g2-64'/>
+<use x='210.869' y='164.777' xlink:href='#g2-51'/>
+<use x='213.515' y='164.777' xlink:href='#g2-54'/>
+<use x='216.162' y='164.777' xlink:href='#g2-48'/>
+<use x='218.808' y='164.777' xlink:href='#g2-48'/>
+<use x='221.454' y='164.777' xlink:href='#g2-77'/>
+<use x='226.072' y='164.777' xlink:href='#g2-104'/>
+<use x='228.805' y='164.777' xlink:href='#g2-122'/>
+<use x='168.285' y='170.755' xlink:href='#g2-49'/>
+<use x='170.931' y='170.755' xlink:href='#g2-54'/>
+<use x='173.578' y='170.755' xlink:href='#g2-45'/>
+<use x='175.342' y='170.755' xlink:href='#g2-99'/>
+<use x='177.694' y='170.755' xlink:href='#g2-111'/>
+<use x='180.193' y='170.755' xlink:href='#g2-114'/>
+<use x='182.001' y='170.755' xlink:href='#g2-101'/>
+<use x='186.118' y='170.755' xlink:href='#g2-65'/>
+<use x='189.646' y='170.755' xlink:href='#g2-77'/>
+<use x='194.264' y='170.755' xlink:href='#g2-68'/>
+<use x='199.851' y='170.755' xlink:href='#g2-53'/>
+<use x='202.497' y='170.755' xlink:href='#g2-57'/>
+<use x='205.144' y='170.755' xlink:href='#g2-53'/>
+<use x='207.79' y='170.755' xlink:href='#g2-48'/>
+<use x='210.436' y='170.755' xlink:href='#g2-120'/>
+<use x='214.639' y='170.755' xlink:href='#g2-64'/>
+<use x='218.168' y='170.755' xlink:href='#g2-51'/>
+<use x='220.814' y='170.755' xlink:href='#g2-46'/>
+<use x='222.285' y='170.755' xlink:href='#g2-52'/>
+<use x='224.931' y='170.755' xlink:href='#g2-71'/>
+<use x='228.459' y='170.755' xlink:href='#g2-104'/>
+<use x='231.192' y='170.755' xlink:href='#g2-122'/>
+<use x='168.285' y='176.733' xlink:href='#g2-85'/>
+<use x='171.917' y='176.733' xlink:href='#g2-98'/>
+<use x='174.65' y='176.733' xlink:href='#g2-117'/>
+<use x='177.383' y='176.733' xlink:href='#g2-110'/>
+<use x='180.116' y='176.733' xlink:href='#g2-116'/>
+<use x='182.027' y='176.733' xlink:href='#g2-117'/>
+<use x='186.524' y='176.733' xlink:href='#g2-50'/>
+<use x='189.17' y='176.733' xlink:href='#g2-48'/>
+<use x='191.817' y='176.733' xlink:href='#g2-46'/>
+<use x='193.287' y='176.733' xlink:href='#g2-48'/>
+<use x='195.933' y='176.733' xlink:href='#g2-52'/>
+<use x='198.58' y='176.733' xlink:href='#g2-44'/>
+<use x='201.814' y='176.733' xlink:href='#g2-71'/>
+<use x='205.343' y='176.733' xlink:href='#g2-67'/>
+<use x='208.724' y='176.733' xlink:href='#g2-67'/>
+<use x='213.87' y='176.733' xlink:href='#g2-57'/>
+<use x='216.516' y='176.733' xlink:href='#g2-46'/>
+<use x='217.986' y='176.733' xlink:href='#g2-51'/>
+<use x='220.633' y='176.733' xlink:href='#g2-46'/>
+<use x='222.103' y='176.733' xlink:href='#g2-48'/>
+<use x='168.285' y='182.71' xlink:href='#g2-51'/>
+<use x='170.931' y='182.71' xlink:href='#g2-50'/>
+<use x='175.342' y='182.71' xlink:href='#g2-108'/>
+<use x='176.604' y='182.71' xlink:href='#g2-111'/>
+<use x='179.251' y='182.71' xlink:href='#g2-103'/>
+<use x='181.897' y='182.71' xlink:href='#g2-105'/>
+<use x='183.16' y='182.71' xlink:href='#g2-99'/>
+<use x='185.512' y='182.71' xlink:href='#g2-97'/>
+<use x='188.055' y='182.71' xlink:href='#g2-108'/>
+<use x='191.082' y='182.71' xlink:href='#g2-99'/>
+<use x='193.434' y='182.71' xlink:href='#g2-111'/>
+<use x='195.933' y='182.71' xlink:href='#g2-114'/>
+<use x='197.741' y='182.71' xlink:href='#g2-101'/>
+<use x='200.093' y='182.71' xlink:href='#g2-115'/>
+<use x='168.285' y='188.688' xlink:href='#g2-50'/>
+<use x='170.931' y='188.688' xlink:href='#g2-48'/>
+<use x='173.578' y='188.688' xlink:href='#g2-50'/>
+<use x='176.224' y='188.688' xlink:href='#g2-49'/>
+<use x='178.87' y='188.688' xlink:href='#g2-45'/>
+<use x='180.635' y='188.688' xlink:href='#g2-48'/>
+<use x='183.281' y='188.688' xlink:href='#g2-49'/>
+<use x='185.927' y='188.688' xlink:href='#g2-45'/>
+<use x='187.692' y='188.688' xlink:href='#g2-51'/>
+<use x='190.338' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -45.308 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 13.361 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 72.03 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.699 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 189.368 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 248.037 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.078 344.392)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.591 344.728)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 77.26 329.897)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-50'/>
+<use x='175.048' y='188.688' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.929 346.003)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.598 338.688)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 253.267 342.782)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -34.847 343.788)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.822 343.05)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.491 305.94)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 141.16 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-53'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-52'/>
+<use x='183.321' y='188.688' xlink:href='#g2-53'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.829 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-54'/>
+<use x='176.558' y='188.688' xlink:href='#g2-49'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-49'/>
+<use x='183.321' y='188.688' xlink:href='#g2-53'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 258.498 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-50'/>
+<use x='176.558' y='188.688' xlink:href='#g2-50'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-52'/>
+<use x='183.321' y='188.688' xlink:href='#g2-57'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.617 338.353)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 29.052 336.071)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.721 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-50'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-55'/>
+<use x='180.675' y='188.688' xlink:href='#g2-49'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.39 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-50'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-53'/>
+<use x='180.675' y='188.688' xlink:href='#g2-48'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 205.059 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-52'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-48'/>
+<use x='180.675' y='188.688' xlink:href='#g2-56'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 263.728 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-50'/>
+<use x='176.558' y='188.688' xlink:href='#g2-50'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-57'/>
+<use x='183.321' y='188.688' xlink:href='#g2-56'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.386 319.563)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-51'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 34.283 309.296)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.952 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-56'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-57'/>
+<use x='180.675' y='188.688' xlink:href='#g2-54'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.621 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-51'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-51'/>
+<use x='180.675' y='188.688' xlink:href='#g2-55'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 210.29 328.488)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-50'/>
+<use x='175.048' y='188.688' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 268.959 344.258)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.156 330.031)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-50'/>
+<use x='175.048' y='188.688' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.513 338.218)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 98.182 272.387)'>
+<use x='168.285' y='188.688' xlink:href='#g2-50'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.851 319.563)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-51'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.52 348.553)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 274.189 345.734)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 -13.925 335.87)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.744 335.87)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.413 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-50'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-51'/>
+<use x='183.321' y='188.688' xlink:href='#g2-54'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 162.082 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-50'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-57'/>
+<use x='183.321' y='188.688' xlink:href='#g2-51'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.751 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-48'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-52'/>
+<use x='183.321' y='188.688' xlink:href='#g2-50'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 279.42 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-49'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-49'/>
+<use x='183.321' y='188.688' xlink:href='#g2-51'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -8.695 306.746)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-53'/>
+<use x='175.048' y='188.688' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.974 340.097)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-48'/>
+<use x='175.048' y='188.688' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.643 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-54'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-55'/>
+<use x='180.675' y='188.688' xlink:href='#g2-57'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 167.312 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-49'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-49'/>
+<use x='183.321' y='188.688' xlink:href='#g2-52'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.981 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-56'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-52'/>
+<use x='180.675' y='188.688' xlink:href='#g2-50'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 284.65 345.734)'>
+<use x='168.285' y='188.688' xlink:href='#g2-48'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.465 327.28)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-50'/>
+<use x='175.048' y='188.688' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 55.204 325.468)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-50'/>
+<use x='175.048' y='188.688' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.873 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-49'/>
+<use x='176.558' y='188.688' xlink:href='#g2-56'/>
+<use x='179.205' y='188.688' xlink:href='#g2-46'/>
+<use x='180.675' y='188.688' xlink:href='#g2-52'/>
+<use x='183.321' y='188.688' xlink:href='#g2-51'/>
+<use x='185.968' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.542 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-53'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-55'/>
+<use x='180.675' y='188.688' xlink:href='#g2-56'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 231.211 278.695)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-57'/>
+<use x='175.048' y='188.688' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 289.88 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-52'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-56'/>
+<use x='180.675' y='188.688' xlink:href='#g2-52'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.766 337.212)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.435 333.655)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 119.104 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-51'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-53'/>
+<use x='180.675' y='188.688' xlink:href='#g2-55'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.773 243.599)'>
+<use x='163.396' y='188.688' xlink:href='#g4-1'/>
+<use x='166.901' y='188.688' xlink:href='#g4-1'/>
+<use x='170.407' y='188.688' xlink:href='#g4-1'/>
+<use x='173.912' y='188.688' xlink:href='#g2-50'/>
+<use x='176.558' y='188.688' xlink:href='#g2-46'/>
+<use x='178.029' y='188.688' xlink:href='#g2-53'/>
+<use x='180.675' y='188.688' xlink:href='#g2-53'/>
+<use x='183.321' y='188.688' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 236.442 332.917)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 295.111 333.789)'>
+<use x='168.285' y='188.688' xlink:href='#g2-49'/>
+<use x='170.931' y='188.688' xlink:href='#g2-46'/>
+<use x='172.401' y='188.688' xlink:href='#g2-49'/>
+<use x='175.048' y='188.688' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -75.53 388.945)'>
+<use x='168.285' y='188.688' xlink:href='#g1-82'/>
+<use x='174.255' y='188.688' xlink:href='#g1-101'/>
+<use x='178.351' y='188.688' xlink:href='#g1-108'/>
+<use x='180.551' y='188.688' xlink:href='#g1-97'/>
+<use x='184.979' y='188.688' xlink:href='#g1-116'/>
+<use x='188.307' y='188.688' xlink:href='#g1-105'/>
+<use x='190.507' y='188.688' xlink:href='#g1-118'/>
+<use x='194.755' y='188.688' xlink:href='#g1-101'/>
+<use x='201.922' y='188.688' xlink:href='#g1-116'/>
+<use x='205.25' y='188.688' xlink:href='#g1-105'/>
+<use x='207.45' y='188.688' xlink:href='#g1-109'/>
+<use x='214.77' y='188.688' xlink:href='#g1-101'/>
+<use x='221.937' y='188.688' xlink:href='#g3-40'/>
+<use x='225.231' y='188.688' xlink:href='#g3-108'/>
+<use x='227.251' y='188.688' xlink:href='#g3-111'/>
+<use x='231.25' y='188.688' xlink:href='#g3-119'/>
+<use x='236.799' y='188.688' xlink:href='#g3-101'/>
+<use x='240.562' y='188.688' xlink:href='#g3-114'/>
+<use x='246.277' y='188.688' xlink:href='#g3-105'/>
+<use x='248.297' y='188.688' xlink:href='#g3-115'/>
+<use x='254.366' y='188.688' xlink:href='#g3-98'/>
+<use x='258.974' y='188.688' xlink:href='#g3-101'/>
+<use x='262.738' y='188.688' xlink:href='#g3-116'/>
+<use x='265.796' y='188.688' xlink:href='#g3-116'/>
+<use x='268.854' y='188.688' xlink:href='#g3-101'/>
+<use x='272.618' y='188.688' xlink:href='#g3-114'/>
+<use x='275.51' y='188.688' xlink:href='#g3-41'/>
+</g>
+<path d='M136.149 309.68H346.746V279.68H136.149Z' fill='#fff'/>
+<path d='M136.149 309.68H346.746V279.68H136.149Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' fill='#933'/>
+<path d='M139.336 290.168H142.324V282.199H139.336ZM145.313 290.168H148.301V284.191H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='191.843' y='175.681' xlink:href='#g3-120'/>
+<use x='195.745' y='175.681' xlink:href='#g3-109'/>
+<use x='202.47' y='175.681' xlink:href='#g3-105'/>
+<use x='204.49' y='175.681' xlink:href='#g3-58'/>
+<use x='206.843' y='175.681' xlink:href='#g0-57'/>
+<use x='210.548' y='175.681' xlink:href='#g0-50'/>
+</g>
+<path d='M177.086 290.168H180.074V282.199H177.086ZM183.063 290.168H186.055V284.191H183.063Z' fill='#bf8080'/>
+<path d='M177.086 290.168H180.074V282.199H177.086ZM183.063 290.168H186.055V284.191H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -38.403 114.479)'>
+<use x='233.123' y='175.681' xlink:href='#g3-109'/>
+<use x='239.848' y='175.681' xlink:href='#g3-105'/>
+<use x='241.869' y='175.681' xlink:href='#g3-58'/>
+<use x='244.221' y='175.681' xlink:href='#g0-57'/>
+<use x='247.926' y='175.681' xlink:href='#g0-50'/>
+</g>
+<path d='M221.895 290.168H224.883V282.199H221.895ZM227.875 290.168H230.863V284.191H227.875Z' fill='#8080bf'/>
+<path d='M221.895 290.168H224.883V282.199H221.895ZM227.875 290.168H230.863V284.191H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='277.134' y='175.681' xlink:href='#g3-116'/>
+<use x='280.192' y='175.681' xlink:href='#g3-99'/>
+<use x='283.956' y='175.681' xlink:href='#g3-58'/>
+<use x='286.308' y='175.681' xlink:href='#g0-54'/>
+<use x='290.013' y='175.681' xlink:href='#g0-49'/>
+</g>
+<path d='M265.109 290.168H268.098V282.199H265.109ZM271.086 290.168H274.074V284.191H271.086Z' fill='#ffb733'/>
+<path d='M265.109 290.168H268.098V282.199H265.109ZM271.086 290.168H274.074V284.191H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='319.615' y='175.681' xlink:href='#g3-106'/>
+<use x='321.871' y='175.681' xlink:href='#g3-101'/>
+<use x='325.634' y='175.681' xlink:href='#g3-58'/>
+<use x='327.987' y='175.681' xlink:href='#g0-53'/>
+<use x='331.691' y='175.681' xlink:href='#g0-56'/>
+</g>
+<path d='M306.859 290.168H309.848V282.199H306.859ZM312.836 290.168H315.824V284.191H312.836Z' fill='#bf80bf'/>
+<path d='M306.859 290.168H309.848V282.199H306.859ZM312.836 290.168H315.824V284.191H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='359.038' y='175.681' xlink:href='#g3-116'/>
+<use x='362.096' y='175.681' xlink:href='#g3-98'/>
+<use x='366.469' y='175.681' xlink:href='#g3-98'/>
+<use x='370.842' y='175.681' xlink:href='#g3-58'/>
+<use x='373.194' y='175.681' xlink:href='#g0-52'/>
+<use x='376.899' y='175.681' xlink:href='#g0-54'/>
+</g>
+<path d='M139.336 303.176H142.324V295.207H139.336ZM145.313 303.176H148.301V297.199H145.313Z' fill='#c96'/>
+<path d='M139.336 303.176H142.324V295.207H139.336ZM145.313 303.176H148.301V297.199H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='191.843' y='188.688' xlink:href='#g3-114'/>
+<use x='194.735' y='188.688' xlink:href='#g3-112'/>
+<use x='199.108' y='188.688' xlink:href='#g3-58'/>
+<use x='201.46' y='188.688' xlink:href='#g0-55'/>
+<use x='205.165' y='188.688' xlink:href='#g0-56'/>
+</g>
+<path d='M177.086 303.176H180.074V295.207H177.086ZM183.063 303.176H186.055V297.199H183.063Z' fill='#80bf80'/>
+<path d='M177.086 303.176H180.074V295.207H177.086ZM183.063 303.176H186.055V297.199H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='233.123' y='188.688' xlink:href='#g3-104'/>
+<use x='237.496' y='188.688' xlink:href='#g3-111'/>
+<use x='241.73' y='188.688' xlink:href='#g3-97'/>
+<use x='245.563' y='188.688' xlink:href='#g3-114'/>
+<use x='248.455' y='188.688' xlink:href='#g3-100'/>
+<use x='252.828' y='188.688' xlink:href='#g3-58'/>
+<use x='255.18' y='188.688' xlink:href='#g0-52'/>
+<use x='258.885' y='188.688' xlink:href='#g0-49'/>
+</g>
+<path d='M221.895 303.176H224.883V295.207H221.895ZM227.875 303.176H230.863V297.199H227.875Z' fill='#bfbf80'/>
+<path d='M221.895 303.176H224.883V295.207H221.895ZM227.875 303.176H230.863V297.199H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='277.134' y='188.688' xlink:href='#g3-109'/>
+<use x='283.859' y='188.688' xlink:href='#g3-101'/>
+<use x='287.622' y='188.688' xlink:href='#g3-115'/>
+<use x='290.869' y='188.688' xlink:href='#g3-104'/>
+<use x='295.241' y='188.688' xlink:href='#g3-58'/>
+<use x='297.593' y='188.688' xlink:href='#g0-52'/>
+<use x='301.298' y='188.688' xlink:href='#g0-49'/>
+</g>
+<path d='M265.109 303.176H268.098V295.207H265.109ZM271.086 303.176H274.074V297.199H271.086Z' fill='#399'/>
+<path d='M265.109 303.176H268.098V295.207H265.109ZM271.086 303.176H274.074V297.199H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='319.615' y='188.688' xlink:href='#g3-103'/>
+<use x='323.849' y='188.688' xlink:href='#g3-108'/>
+<use x='325.869' y='188.688' xlink:href='#g3-105'/>
+<use x='327.89' y='188.688' xlink:href='#g3-98'/>
+<use x='332.498' y='188.688' xlink:href='#g3-99'/>
+<use x='336.261' y='188.688' xlink:href='#g3-58'/>
+<use x='338.614' y='188.688' xlink:href='#g0-51'/>
+<use x='342.318' y='188.688' xlink:href='#g0-57'/>
+</g>
+<path d='M306.859 303.176H309.848V295.207H306.859ZM312.836 303.176H315.824V297.199H312.836Z' fill='#d9b3b3'/>
+<path d='M306.859 303.176H309.848V295.207H306.859ZM312.836 303.176H315.824V297.199H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='359.038' y='188.688' xlink:href='#g3-115'/>
+<use x='362.285' y='188.688' xlink:href='#g3-109'/>
+<use x='369.009' y='188.688' xlink:href='#g3-105'/>
+<use x='371.03' y='188.688' xlink:href='#g3-58'/>
+<use x='373.382' y='188.688' xlink:href='#g0-54'/>
+<use x='377.087' y='188.688' xlink:href='#g0-50'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg b/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg
new file mode 100644 (file)
index 0000000..bc91c21
--- /dev/null
@@ -0,0 +1,955 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.629pt' height='170.383pt' viewBox='52.934 54.994 381.629 170.383'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip3'>
+<path d='M82.148 209.23H434.164V83.984H82.148Z'/>
+</clipPath>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-102' xlink:href='#g0-102' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-109' d='M6.581-2.663C6.581-3.327 6.402-4.08 5.317-4.08C4.564-4.08 4.142-3.622 3.927-3.344C3.865-3.524 3.676-4.08 2.762-4.08C2.053-4.08 1.623-3.667 1.417-3.398V-4.035H.726V0H1.47V-2.188C1.47-2.78 1.704-3.497 2.385-3.497C3.282-3.497 3.282-2.86 3.282-2.6V0H4.026V-2.188C4.026-2.78 4.259-3.497 4.94-3.497C5.837-3.497 5.837-2.86 5.837-2.6V0H6.581V-2.663Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-102' d='M1.325-2.657H2.12V-3.096H1.304V-3.898C1.304-4.38 1.743-4.449 1.974-4.449C2.12-4.449 2.308-4.428 2.566-4.331V-4.84C2.385-4.882 2.169-4.91 1.981-4.91C1.262-4.91 .739-4.394 .739-3.703V-3.096H.202V-2.657H.739V0H1.325V-2.657Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+</defs>
+<g id='page3'>
+<path d='M140.82 218.086V209.23M199.488 218.086V209.23M258.156 218.086V209.23M316.824 218.086V209.23M375.496 218.086V209.23M140.82 75.129V83.984M199.488 75.129V83.984M258.156 75.129V83.984M316.824 75.129V83.984M375.496 75.129V83.984' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M111.484 213.484V209.23M170.152 213.484V209.23M228.824 213.484V209.23M287.492 213.484V209.23M346.16 213.484V209.23M404.828 213.484V209.23M111.484 79.734V83.984M170.152 79.734V83.984M228.824 79.734V83.984M287.492 79.734V83.984M346.16 79.734V83.984M404.828 79.734V83.984' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 209.23H86.402M82.148 177.918H86.402M82.148 146.609H86.402M82.148 115.297H86.402M82.148 83.984H86.402M434.164 209.23H429.91M434.164 177.918H429.91M434.164 146.609H429.91M434.164 115.297H429.91M434.164 83.984H429.91' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 209.23V83.984H434.164V209.23H82.148Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-99'/>
+<use x='118.25' y='188.674' xlink:href='#g3-102'/>
+<use x='120.838' y='188.674' xlink:href='#g3-114'/>
+<use x='123.73' y='188.674' xlink:href='#g3-97'/>
+<use x='127.798' y='188.674' xlink:href='#g3-99'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-108'/>
+<use x='116.507' y='188.674' xlink:href='#g3-101'/>
+<use x='120.271' y='188.674' xlink:href='#g3-97'/>
+<use x='124.339' y='188.674' xlink:href='#g3-110'/>
+<use x='128.711' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-114'/>
+<use x='117.379' y='188.674' xlink:href='#g3-101'/>
+<use x='121.142' y='188.674' xlink:href='#g3-100'/>
+<use x='125.515' y='188.674' xlink:href='#g3-105'/>
+<use x='127.535' y='188.674' xlink:href='#g3-115'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-108'/>
+<use x='116.507' y='188.674' xlink:href='#g3-97'/>
+<use x='120.34' y='188.674' xlink:href='#g3-114'/>
+<use x='123.232' y='188.674' xlink:href='#g3-115'/>
+<use x='126.478' y='188.674' xlink:href='#g3-111'/>
+<use x='130.712' y='188.674' xlink:href='#g3-110'/>
+<use x='135.085' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-109'/>
+<use x='121.211' y='188.674' xlink:href='#g3-115'/>
+<use x='124.458' y='188.674' xlink:href='#g3-116'/>
+<use x='127.516' y='188.674' xlink:href='#g3-114'/>
+<use x='130.408' y='188.674' xlink:href='#g3-101'/>
+<use x='134.171' y='188.674' xlink:href='#g3-115'/>
+<use x='137.418' y='188.674' xlink:href='#g3-115'/>
+<use x='140.664' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' y='188.674' xlink:href='#g3-114'/>
+<use x='117.379' y='188.674' xlink:href='#g3-112'/>
+<use x='121.751' y='188.674' xlink:href='#g3-116'/>
+<use x='124.809' y='188.674' xlink:href='#g3-101'/>
+<use x='128.573' y='188.674' xlink:href='#g3-115'/>
+<use x='131.819' y='188.674' xlink:href='#g3-116'/>
+<use x='134.877' y='188.674' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
+<use x='114.487' y='188.674' xlink:href='#g2-50'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-120'/>
+</g>
+<path d='M82.148 146.609H434.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M86.328 209.23H89.566V146.609H86.328ZM144.996 209.23H148.234V146.609H144.996ZM203.668 209.23H206.902V146.609H203.668ZM262.336 209.23H265.574V146.609H262.336ZM321.004 209.23H324.242V146.609H321.004ZM379.672 209.23H382.91V146.609H379.672Z' fill='#933' clip-path='url(#clip3)'/>
+<path d='M86.328 209.23H89.566V146.609H86.328ZM144.996 209.23H148.234V146.609H144.996ZM203.668 209.23H206.902V146.609H203.668ZM262.336 209.23H265.574V146.609H262.336ZM321.004 209.23H324.242V146.609H321.004ZM379.672 209.23H382.91V146.609H379.672Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M87.949 146.609' fill='#933' clip-path='url(#clip3)'/>
+<path d='M85.953 146.609H89.938' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M87.949 146.609' fill='#933' clip-path='url(#clip3)'/>
+<path d='M85.953 146.609H89.938' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M146.617 146.609V146.105' fill='#933' clip-path='url(#clip3)'/>
+<path d='M146.617 146.609V146.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M144.625 146.105H148.609' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M146.617 146.609V147.109' fill='#933' clip-path='url(#clip3)'/>
+<path d='M146.617 146.609V147.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M148.61 147.109H144.625' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M205.285 146.609V146.359' fill='#933' clip-path='url(#clip3)'/>
+<path d='M205.285 146.609V146.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M203.293 146.36H207.277' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M205.285 146.609V146.859' fill='#933' clip-path='url(#clip3)'/>
+<path d='M205.285 146.609V146.859' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M207.278 146.86H203.293' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M263.953 146.609V145.105' fill='#933' clip-path='url(#clip3)'/>
+<path d='M263.953 146.609V145.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M261.961 145.105H265.945' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M263.953 146.609V148.109' fill='#933' clip-path='url(#clip3)'/>
+<path d='M263.953 146.609V148.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M265.949 148.109H261.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M322.625 146.609V144.73' fill='#933' clip-path='url(#clip3)'/>
+<path d='M322.625 146.609V144.73' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M320.629 144.73H324.617' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M322.625 146.609V148.488' fill='#933' clip-path='url(#clip3)'/>
+<path d='M322.625 146.609V148.488' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M324.617 148.488H320.633' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M381.293 146.609V140.785' fill='#933' clip-path='url(#clip3)'/>
+<path d='M381.293 146.609V140.785' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M379.301 140.785H383.285' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M381.293 146.609V152.434' fill='#933' clip-path='url(#clip3)'/>
+<path d='M381.293 146.609V152.434' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M383.285 152.434H379.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M91.559 209.23H94.797V146.23H91.559ZM150.227 209.23H153.465V146.547H150.227ZM208.899 209.23H212.133V145.293H208.899ZM267.567 209.23H270.805V152.117H267.567ZM326.234 209.23H329.473V140.973H326.234ZM384.902 209.23H388.141V154.562H384.902Z' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M91.559 209.23H94.797V146.23H91.559ZM150.227 209.23H153.465V146.547H150.227ZM208.899 209.23H212.133V145.293H208.899ZM267.567 209.23H270.805V152.117H267.567ZM326.234 209.23H329.473V140.973H326.234ZM384.902 209.23H388.141V154.562H384.902Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M93.18 146.23V146.168' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M93.18 146.23V146.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M91.184 146.168H95.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M93.18 146.23V146.297' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M93.18 146.23V146.297' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M95.172 146.297H91.187' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M151.848 146.547V146.297' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M151.848 146.547V146.297' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M149.855 146.297H153.84' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M151.848 146.547V146.797' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M151.848 146.547V146.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M153.84 146.797H149.855' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M210.516 145.293V145.105' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M210.516 145.293V145.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M208.523 145.105H212.507' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M210.516 145.293V145.48' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M210.516 145.293V145.48' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M212.508 145.481H208.523' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M269.184 152.117V151.555' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M269.184 152.117V151.555' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M267.191 151.554H271.175' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M269.184 152.117V152.684' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M269.184 152.117V152.684' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M271.179 152.684H267.191' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M327.856 140.973V137.402' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M327.856 140.973V137.402' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M325.859 137.403H329.847' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M327.856 140.973V144.543' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M327.856 140.973V144.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M329.847 144.543H325.863' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M386.524 154.562V147.734' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M386.524 154.562V147.734' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M384.531 147.734H388.515' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M386.524 154.562V161.387' fill='#bf8080' clip-path='url(#clip3)'/>
+<path d='M386.524 154.562V161.387' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M388.515 161.387H384.531' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M96.789 209.23H100.027V145.293H96.789ZM155.457 209.23H158.695V143.101H155.457ZM214.129 209.23H217.363V144.668H214.129ZM272.797 209.23H276.035V141.973H272.797ZM331.465 209.23H334.703V143.101H331.465ZM390.133 209.23H393.371V83.984H390.133Z' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M96.789 209.23H100.027V145.293H96.789ZM155.457 209.23H158.695V143.101H155.457ZM214.129 209.23H217.363V144.668H214.129ZM272.797 209.23H276.035V141.973H272.797ZM331.465 209.23H334.703V143.101H331.465ZM390.133 209.23H393.371V83.984H390.133Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M98.41 145.293V145.23' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M98.41 145.293V145.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M96.414 145.23H100.399' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M98.41 145.293V145.355' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M98.41 145.293V145.355' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M100.402 145.356H96.418' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M157.078 143.101V142.601' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M157.078 143.101V142.601' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M155.086 142.601H159.071' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M157.078 143.101V143.601' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M157.078 143.101V143.601' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M159.071 143.601H155.086' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M215.746 144.668V144.543' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M215.746 144.668V144.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M213.754 144.543H217.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M215.746 144.668V144.793' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M215.746 144.668V144.793' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M217.739 144.793H213.754' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M274.414 141.973V141.535' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M274.414 141.973V141.535' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M272.422 141.536H276.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M274.414 141.973V142.414' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M274.414 141.973V142.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M276.41 142.414H272.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M333.086 143.101V141.66' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M333.086 143.101V141.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M331.09 141.66H335.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M333.086 143.101V144.543' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M333.086 143.101V144.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M335.078 144.543H331.094' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M391.754 83.984' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M389.762 83.984H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M391.754 83.984' fill='#8080bf' clip-path='url(#clip3)'/>
+<path d='M389.762 83.984H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M102.02 209.23H105.258V143.289H102.02ZM160.688 209.23H163.926V146.484H160.688ZM219.359 209.23H222.594V134.711H219.359ZM278.027 209.23H281.266V139.531H278.027ZM336.695 209.23H339.934V83.984H336.695ZM395.363 209.23H398.602V128.008H395.363Z' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M102.02 209.23H105.258V143.289H102.02ZM160.688 209.23H163.926V146.484H160.688ZM219.359 209.23H222.594V134.711H219.359ZM278.027 209.23H281.266V139.531H278.027ZM336.695 209.23H339.934V83.984H336.695ZM395.363 209.23H398.602V128.008H395.363Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M103.641 143.289' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M101.644 143.289H105.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M103.641 143.289' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M101.644 143.289H105.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M162.309 146.484V146.168' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M162.309 146.484V146.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M160.316 146.168H164.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M162.309 146.484V146.797' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M162.309 146.484V146.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M164.301 146.797H160.316' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M220.977 134.711V134.523' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M220.977 134.711V134.523' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M218.984 134.524H222.969' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M220.977 134.711V134.898' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M220.977 134.711V134.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M222.969 134.899H218.984' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M279.645 139.531V139.469' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M279.645 139.531V139.469' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M277.652 139.469H281.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M279.645 139.531V139.594' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M279.645 139.531V139.594' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M281.64 139.593H277.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M338.317 83.984' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M336.32 83.984H340.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M338.317 83.984' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M336.32 83.984H340.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M396.984 128.008V115.859' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M396.984 128.008V115.859' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M394.992 115.859H398.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M396.984 128.008V140.156' fill='#ffb733' clip-path='url(#clip3)'/>
+<path d='M396.984 128.008V140.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M398.976 140.156H394.992' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M107.25 209.23H110.488V127.82H107.25ZM165.918 209.23H169.156V145.105H165.918ZM224.59 209.23H227.824V112.98H224.59ZM283.258 209.23H286.496V115.109H283.258ZM341.926 209.23H345.164V103.961H341.926ZM400.594 209.23H403.832V136.715H400.594Z' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M107.25 209.23H110.488V127.82H107.25ZM165.918 209.23H169.156V145.105H165.918ZM224.59 209.23H227.824V112.98H224.59ZM283.258 209.23H286.496V115.109H283.258ZM341.926 209.23H345.164V103.961H341.926ZM400.594 209.23H403.832V136.715H400.594Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M108.871 127.82V127.758' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M108.871 127.82V127.758' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M106.875 127.758H110.86' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M108.871 127.82V127.883' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M108.871 127.82V127.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M110.864 127.883H106.879' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M167.539 145.105V144.668' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M167.539 145.105V144.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M165.547 144.668H169.532' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M167.539 145.105V145.543' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M167.539 145.105V145.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M169.532 145.543H165.547' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M226.207 112.98V112.73' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M226.207 112.98V112.73' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M224.215 112.73H228.2' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M226.207 112.98V113.23' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M226.207 112.98V113.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M228.2 113.23H224.215' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M284.875 115.109V113.605' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M284.875 115.109V113.605' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M282.883 113.606H286.868' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M284.875 115.109V116.613' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M284.875 115.109V116.613' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M286.868 116.614H282.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M343.547 103.961V102.961' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M343.547 103.961V102.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M341.551 102.961H345.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M343.547 103.961V104.965' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M343.547 103.961V104.965' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M345.539 104.965H341.555' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M402.215 136.715V130.137' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M402.215 136.715V130.137' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M400.223 130.136H404.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M402.215 136.715V143.289' fill='#bf80bf' clip-path='url(#clip3)'/>
+<path d='M402.215 136.715V143.289' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M404.207 143.289H400.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M112.481 209.23H115.719V144.918H112.481ZM171.149 209.23H174.387V147.984H171.149ZM229.82 209.23H233.055V134.461H229.82ZM288.488 209.23H291.727V147.734H288.488ZM347.156 209.23H350.395V83.984H347.156ZM405.824 209.23H409.063V123.562H405.824Z' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M112.481 209.23H115.719V144.918H112.481ZM171.149 209.23H174.387V147.984H171.149ZM229.82 209.23H233.055V134.461H229.82ZM288.488 209.23H291.727V147.734H288.488ZM347.156 209.23H350.395V83.984H347.156ZM405.824 209.23H409.063V123.562H405.824Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M114.098 144.918V144.855' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M114.098 144.918V144.855' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M112.105 144.856H116.09' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M114.098 144.918V144.98' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M114.098 144.918V144.98' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M116.094 144.981H112.109' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M172.77 147.984V147.359' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M172.77 147.984V147.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M170.777 147.36H174.762' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M172.77 147.984V148.613' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M172.77 147.984V148.613' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M174.762 148.613H170.777' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M231.438 134.461V134.336' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M231.438 134.461V134.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M229.445 134.336H233.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M231.438 134.461V134.586' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M231.438 134.461V134.586' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M233.43 134.586H229.445' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M290.106 147.734V146.297' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M290.106 147.734V146.297' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M288.113 146.297H292.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M290.106 147.734V149.176' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M290.106 147.734V149.176' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M292.098 149.176H288.113' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M348.777 83.984' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M346.781 83.984H350.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M348.777 83.984' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M346.781 83.984H350.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M407.445 123.562V105.965' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M407.445 123.562V105.965' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M405.453 105.965H409.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M407.445 123.562V141.16' fill='#c96' clip-path='url(#clip3)'/>
+<path d='M407.445 123.562V141.16' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M409.437 141.16H405.453' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M117.711 209.23H120.949V143.601H117.711ZM176.379 209.23H179.617V139.781H176.379ZM235.051 209.23H238.285V126.57H235.051ZM293.719 209.23H296.957V83.984H293.719ZM352.387 209.23H355.625V83.984H352.387ZM411.055 209.23H414.293V83.984H411.055Z' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M117.711 209.23H120.949V143.601H117.711ZM176.379 209.23H179.617V139.781H176.379ZM235.051 209.23H238.285V126.57H235.051ZM293.719 209.23H296.957V83.984H293.719ZM352.387 209.23H355.625V83.984H352.387ZM411.055 209.23H414.293V83.984H411.055Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M119.328 143.601V143.539' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M119.328 143.601V143.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M117.336 143.539H121.321' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M119.328 143.601V143.664' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M119.328 143.601V143.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M121.325 143.664H117.34' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M178 139.781V139.469' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M178 139.781V139.469' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M176.008 139.469H179.993' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M178 139.781V140.094' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M178 139.781V140.094' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M179.993 140.093H176.008' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M236.668 126.57V126.445' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M236.668 126.57V126.445' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M234.676 126.446H238.661' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M236.668 126.57V126.695' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M236.668 126.57V126.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M238.66 126.695H234.675' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M295.336 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M293.344 83.984H297.329' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M295.336 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M293.344 83.984H297.329' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M354.008 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M352.012 83.984H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M354.008 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M352.012 83.984H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M412.676 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M410.684 83.984H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M412.676 83.984' fill='#80bf80' clip-path='url(#clip3)'/>
+<path d='M410.684 83.984H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M122.941 209.23H126.18V140.094H122.941ZM181.609 209.23H184.848V131.141H181.609ZM240.281 209.23H243.516V136.902H240.281ZM298.949 209.23H302.188V83.984H298.949ZM357.617 209.23H360.856V83.984H357.617ZM416.285 209.23H419.524V83.984H416.285Z' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M122.941 209.23H126.18V140.094H122.941ZM181.609 209.23H184.848V131.141H181.609ZM240.281 209.23H243.516V136.902H240.281ZM298.949 209.23H302.188V83.984H298.949ZM357.617 209.23H360.856V83.984H357.617ZM416.285 209.23H419.524V83.984H416.285Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M124.559 140.094V140.031' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M124.559 140.094V140.031' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M122.566 140.032H126.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M124.559 140.094V140.156' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M124.559 140.094V140.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M126.555 140.156H122.57' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M183.231 131.141V130.703' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M183.231 131.141V130.703' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M181.238 130.703H185.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M183.231 131.141V131.578' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M183.231 131.141V131.578' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M185.223 131.579H181.238' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M241.899 136.902V136.652' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M241.899 136.902V136.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M239.906 136.652H243.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M241.899 136.902V137.152' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M241.899 136.902V137.152' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M243.891 137.152H239.906' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M300.567 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M298.574 83.984H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M300.567 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M298.574 83.984H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M359.238 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M357.242 83.984H361.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M359.238 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M357.242 83.984H361.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M417.906 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M415.914 83.984H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M417.906 83.984' fill='#bfbf80' clip-path='url(#clip3)'/>
+<path d='M415.914 83.984H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M128.172 209.23H131.41V141.348H128.172ZM186.84 209.23H190.078V135.273H186.84ZM245.512 209.23H248.746V138.344H245.512ZM304.18 209.23H307.418V113.73H304.18ZM362.848 209.23H366.086V83.984H362.848ZM421.516 209.23H424.754V127.195H421.516Z' fill='#399' clip-path='url(#clip3)'/>
+<path d='M128.172 209.23H131.41V141.348H128.172ZM186.84 209.23H190.078V135.273H186.84ZM245.512 209.23H248.746V138.344H245.512ZM304.18 209.23H307.418V113.73H304.18ZM362.848 209.23H366.086V83.984H362.848ZM421.516 209.23H424.754V127.195H421.516Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M129.789 141.348V141.285' fill='#399' clip-path='url(#clip3)'/>
+<path d='M129.789 141.348V141.285' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M127.797 141.285H131.782' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M129.789 141.348V141.41' fill='#399' clip-path='url(#clip3)'/>
+<path d='M129.789 141.348V141.41' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M131.785 141.41H127.8' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M188.461 135.273V134.711' fill='#399' clip-path='url(#clip3)'/>
+<path d='M188.461 135.273V134.711' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M186.469 134.711H190.454' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M188.461 135.273V135.836' fill='#399' clip-path='url(#clip3)'/>
+<path d='M188.461 135.273V135.836' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M190.453 135.836H186.468' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M247.129 138.344V138.09' fill='#399' clip-path='url(#clip3)'/>
+<path d='M247.129 138.344V138.09' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M245.137 138.089H249.122' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M247.129 138.344V138.594' fill='#399' clip-path='url(#clip3)'/>
+<path d='M247.129 138.344V138.594' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M249.121 138.593H245.136' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M305.797 113.73V112.855' fill='#399' clip-path='url(#clip3)'/>
+<path d='M305.797 113.73V112.855' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M303.804 112.855H307.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M305.797 113.73V114.609' fill='#399' clip-path='url(#clip3)'/>
+<path d='M305.797 113.73V114.609' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M307.789 114.61H303.804' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M364.469 83.984' fill='#399' clip-path='url(#clip3)'/>
+<path d='M362.473 83.984H366.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M364.469 83.984' fill='#399' clip-path='url(#clip3)'/>
+<path d='M362.473 83.984H366.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M423.137 127.195V122.246' fill='#399' clip-path='url(#clip3)'/>
+<path d='M423.137 127.195V122.246' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M421.144 122.246H425.128' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M423.137 127.195V132.141' fill='#399' clip-path='url(#clip3)'/>
+<path d='M423.137 127.195V132.141' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M425.129 132.14H421.144' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M133.402 209.23H136.641V140.91H133.402ZM192.07 209.23H195.309V145.98H192.07ZM250.742 209.23H253.977V141.098H250.742ZM309.41 209.23H312.649V124.816H309.41ZM368.078 209.23H371.317V83.984H368.078ZM426.746 209.23H429.984V123.937H426.746Z' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M133.402 209.23H136.641V140.91H133.402ZM192.07 209.23H195.309V145.98H192.07ZM250.742 209.23H253.977V141.098H250.742ZM309.41 209.23H312.649V124.816H309.41ZM368.078 209.23H371.317V83.984H368.078ZM426.746 209.23H429.984V123.937H426.746Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M135.02 140.91V140.848' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M135.02 140.91V140.848' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M133.027 140.848H137.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M135.02 140.91V140.973' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M135.02 140.91V140.973' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M137.016 140.973H133.031' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M193.692 145.98V144.918' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M193.692 145.98V144.918' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M191.699 144.918H195.684' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M193.692 145.98V147.047' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M193.692 145.98V147.047' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M195.684 147.046H191.699' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M252.359 141.098V140.973' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M252.359 141.098V140.973' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M250.367 140.973H254.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M252.359 141.098V141.223' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M252.359 141.098V141.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M254.352 141.223H250.367' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M311.027 124.816V123.937' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M311.027 124.816V123.937' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M309.035 123.938H313.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M311.027 124.816V125.691' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M311.027 124.816V125.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M313.02 125.691H309.035' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M369.699 83.984' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M367.703 83.984H371.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M369.699 83.984' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M367.703 83.984H371.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M428.367 123.937V119.867' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M428.367 123.937V119.867' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M426.375 119.867H430.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M428.367 123.937V128.008' fill='#d9b3b3' clip-path='url(#clip3)'/>
+<path d='M428.367 123.937V128.008' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<path d='M430.36 128.008H426.375' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip3)'/>
+<g transform='matrix(0 -1 1 0 -99.092 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.423 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 18.246 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 76.915 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.584 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 194.253 255.07)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -93.862 254.695)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.193 255.008)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 23.476 253.755)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 82.145 260.581)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.814 249.434)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 199.483 263.023)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-56'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -88.631 253.755)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -29.962 251.563)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 28.707 253.129)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 87.376 250.436)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.045 251.563)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 204.714 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-51'/>
+<use x='126.877' y='188.674' xlink:href='#g2-50'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -83.401 251.751)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -24.732 254.945)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 33.937 243.172)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 92.606 247.994)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.275 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-52'/>
+<use x='126.877' y='188.674' xlink:href='#g2-55'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 209.944 236.471)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.17 236.283)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.501 253.567)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.168 221.442)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 97.837 223.571)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.506 212.424)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-54'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 215.175 245.176)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -72.94 253.38)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -14.271 256.448)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.398 242.922)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.067 256.198)'>
+<use x='114.487' y='188.674' xlink:href='#g2-48'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-57'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 161.736 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-50'/>
+<use x='126.877' y='188.674' xlink:href='#g2-51'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 220.405 232.025)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -67.709 252.064)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -9.04 248.244)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.629 235.031)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.298 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-53'/>
+<use x='126.877' y='188.674' xlink:href='#g2-54'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 166.967 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-49'/>
+<use x='122.76' y='188.674' xlink:href='#g2-48'/>
+<use x='125.406' y='188.674' xlink:href='#g2-46'/>
+<use x='126.877' y='188.674' xlink:href='#g2-51'/>
+<use x='129.523' y='188.674' xlink:href='#g2-50'/>
+<use x='132.169' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 225.636 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-51'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-48'/>
+<use x='126.877' y='188.674' xlink:href='#g2-56'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.479 248.558)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.81 239.602)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-50'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 54.859 245.364)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.528 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-55'/>
+<use x='125.406' y='188.674' xlink:href='#g2-51'/>
+<use x='128.053' y='188.674' xlink:href='#g2-46'/>
+<use x='129.523' y='188.674' xlink:href='#g2-52'/>
+<use x='132.169' y='188.674' xlink:href='#g2-53'/>
+<use x='134.816' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.197 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-54'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-48'/>
+<use x='126.877' y='188.674' xlink:href='#g2-54'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 230.866 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-50'/>
+<use x='126.877' y='188.674' xlink:href='#g2-52'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -57.249 249.81)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.42 243.736)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.089 246.804)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-49'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 118.758 222.193)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-53'/>
+<use x='121.25' y='188.674' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.427 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-52'/>
+<use x='126.877' y='188.674' xlink:href='#g2-56'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 236.096 235.657)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 -52.018 249.372)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.651 254.444)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 65.32 249.56)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-48'/>
+<use x='121.25' y='188.674' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 123.989 233.278)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.658 192.447)'>
+<use x='109.598' y='188.674' xlink:href='#g4-1'/>
+<use x='113.103' y='188.674' xlink:href='#g4-1'/>
+<use x='116.608' y='188.674' xlink:href='#g4-1'/>
+<use x='120.114' y='188.674' xlink:href='#g2-50'/>
+<use x='122.76' y='188.674' xlink:href='#g2-46'/>
+<use x='124.23' y='188.674' xlink:href='#g2-51'/>
+<use x='126.877' y='188.674' xlink:href='#g2-49'/>
+<use x='129.523' y='188.674' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 241.327 232.401)'>
+<use x='114.487' y='188.674' xlink:href='#g2-49'/>
+<use x='117.133' y='188.674' xlink:href='#g2-46'/>
+<use x='118.603' y='188.674' xlink:href='#g2-51'/>
+<use x='121.25' y='188.674' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -129.314 316.355)'>
+<use x='114.487' y='188.674' xlink:href='#g1-82'/>
+<use x='120.457' y='188.674' xlink:href='#g1-101'/>
+<use x='124.553' y='188.674' xlink:href='#g1-108'/>
+<use x='126.753' y='188.674' xlink:href='#g1-97'/>
+<use x='131.181' y='188.674' xlink:href='#g1-116'/>
+<use x='134.509' y='188.674' xlink:href='#g1-105'/>
+<use x='136.709' y='188.674' xlink:href='#g1-118'/>
+<use x='140.957' y='188.674' xlink:href='#g1-101'/>
+<use x='148.124' y='188.674' xlink:href='#g1-116'/>
+<use x='151.452' y='188.674' xlink:href='#g1-105'/>
+<use x='153.652' y='188.674' xlink:href='#g1-109'/>
+<use x='160.972' y='188.674' xlink:href='#g1-101'/>
+<use x='168.139' y='188.674' xlink:href='#g3-40'/>
+<use x='171.432' y='188.674' xlink:href='#g3-108'/>
+<use x='173.453' y='188.674' xlink:href='#g3-111'/>
+<use x='177.452' y='188.674' xlink:href='#g3-119'/>
+<use x='183' y='188.674' xlink:href='#g3-101'/>
+<use x='186.764' y='188.674' xlink:href='#g3-114'/>
+<use x='192.479' y='188.674' xlink:href='#g3-105'/>
+<use x='194.499' y='188.674' xlink:href='#g3-115'/>
+<use x='200.568' y='188.674' xlink:href='#g3-98'/>
+<use x='205.176' y='188.674' xlink:href='#g3-101'/>
+<use x='208.94' y='188.674' xlink:href='#g3-116'/>
+<use x='211.998' y='188.674' xlink:href='#g3-116'/>
+<use x='215.056' y='188.674' xlink:href='#g3-101'/>
+<use x='218.819' y='188.674' xlink:href='#g3-114'/>
+<use x='221.711' y='188.674' xlink:href='#g3-41'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg b/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg
new file mode 100644 (file)
index 0000000..e8b04a0
--- /dev/null
@@ -0,0 +1,1269 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.627pt' height='259.632pt' viewBox='106.732 54.993 381.627 259.632'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip4'>
+<path d='M135.949 251.93H487.961V84.164H135.949Z'/>
+</clipPath>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-45' xlink:href='#g0-45' transform='scale(1.143)'/>
+<use id='g3-49' xlink:href='#g0-49' transform='scale(1.143)'/>
+<use id='g3-54' xlink:href='#g0-54' transform='scale(1.143)'/>
+<use id='g3-56' xlink:href='#g0-56' transform='scale(1.143)'/>
+<use id='g3-58' xlink:href='#g0-58' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-103' xlink:href='#g0-103' transform='scale(1.143)'/>
+<use id='g3-104' xlink:href='#g0-104' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-106' xlink:href='#g0-106' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g3-120' xlink:href='#g0-120' transform='scale(1.143)'/>
+<use id='g2-41' xlink:href='#g0-41' transform='scale(.714)'/>
+<use id='g2-44' xlink:href='#g0-44' transform='scale(.714)'/>
+<use id='g2-45' xlink:href='#g0-45' transform='scale(.714)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-64' xlink:href='#g0-64' transform='scale(.714)'/>
+<use id='g2-67' xlink:href='#g0-67' transform='scale(.714)'/>
+<use id='g2-71' xlink:href='#g0-71' transform='scale(.714)'/>
+<use id='g2-73' xlink:href='#g0-73' transform='scale(.714)'/>
+<use id='g2-85' xlink:href='#g0-85' transform='scale(.714)'/>
+<use id='g2-88' xlink:href='#g0-88' transform='scale(.714)'/>
+<use id='g2-97' xlink:href='#g0-97' transform='scale(.714)'/>
+<use id='g2-98' xlink:href='#g0-98' transform='scale(.714)'/>
+<use id='g2-99' xlink:href='#g0-99' transform='scale(.714)'/>
+<use id='g2-100' xlink:href='#g0-100' transform='scale(.714)'/>
+<use id='g2-101' xlink:href='#g0-101' transform='scale(.714)'/>
+<use id='g2-103' xlink:href='#g0-103' transform='scale(.714)'/>
+<use id='g2-104' xlink:href='#g0-104' transform='scale(.714)'/>
+<use id='g2-105' xlink:href='#g0-105' transform='scale(.714)'/>
+<use id='g2-108' xlink:href='#g0-108' transform='scale(.714)'/>
+<use id='g2-109' xlink:href='#g0-109' transform='scale(.714)'/>
+<use id='g2-110' xlink:href='#g0-110' transform='scale(.714)'/>
+<use id='g2-111' xlink:href='#g0-111' transform='scale(.714)'/>
+<use id='g2-114' xlink:href='#g0-114' transform='scale(.714)'/>
+<use id='g2-115' xlink:href='#g0-115' transform='scale(.714)'/>
+<use id='g2-116' xlink:href='#g0-116' transform='scale(.714)'/>
+<use id='g2-117' xlink:href='#g0-117' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<use id='g2-122' xlink:href='#g0-122' transform='scale(.714)'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g4-2' d='M4.13-2.481C4.184-2.535 4.204-2.57 4.204-2.615C4.204-2.69 4.139-2.755 4.065-2.755C4.01-2.755 3.985-2.73 3.93-2.675L2.7-1.445L1.465-2.68C1.41-2.735 1.375-2.755 1.33-2.755C1.255-2.755 1.191-2.69 1.191-2.615C1.191-2.56 1.215-2.535 1.27-2.481L2.501-1.245L1.27-.01C1.215 .045 1.191 .07 1.191 .125C1.191 .199 1.255 .264 1.33 .264C1.385 .264 1.41 .239 1.46 .189L2.695-1.046L3.97 .229C3.995 .249 4.03 .264 4.065 .264C4.139 .264 4.204 .199 4.204 .125C4.204 .095 4.194 .075 4.184 .05C4.164 .02 3.238-.892 2.894-1.245L4.13-2.481Z'/>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-109' d='M6.581-2.663C6.581-3.327 6.402-4.08 5.317-4.08C4.564-4.08 4.142-3.622 3.927-3.344C3.865-3.524 3.676-4.08 2.762-4.08C2.053-4.08 1.623-3.667 1.417-3.398V-4.035H.726V0H1.47V-2.188C1.47-2.78 1.704-3.497 2.385-3.497C3.282-3.497 3.282-2.86 3.282-2.6V0H4.026V-2.188C4.026-2.78 4.259-3.497 4.94-3.497C5.837-3.497 5.837-2.86 5.837-2.6V0H6.581V-2.663Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-44' d='M1.339-.007V-.628H.711V0H.907L.704 .893H1.018L1.339-.007Z'/>
+<path id='g0-45' d='M2.05-1.332V-1.771H.084V-1.332H2.05Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-58' d='M1.339-3.096H.711V-2.469H1.339V-3.096ZM.711-.628V0H1.339V-.628H.711Z'/>
+<path id='g0-64' d='M4.142-.614C4.038-.614 4.024-.614 3.968-.586C3.626-.467 3.271-.391 2.901-.391C1.778-.391 .976-1.339 .976-2.42C.976-3.592 1.883-4.449 2.859-4.449C3.055-4.449 3.515-4.4 3.745-3.843C3.55-3.954 3.333-4.003 3.152-4.003C2.406-4.003 1.778-3.306 1.778-2.42C1.778-1.513 2.427-.837 3.145-.837C3.689-.837 4.519-1.276 4.519-2.518C4.519-3.222 4.47-4.91 2.866-4.91C1.541-4.91 .411-3.815 .411-2.42C.411-1.039 1.527 .07 2.873 .07C3.515 .07 4.115-.195 4.519-.614H4.142ZM3.152-1.297C2.72-1.297 2.343-1.778 2.343-2.42C2.343-3.082 2.734-3.543 3.145-3.543C3.578-3.543 3.954-3.062 3.954-2.42C3.954-1.757 3.564-1.297 3.152-1.297Z'/>
+<path id='g0-67' d='M4.317-.851C3.829-.551 3.605-.418 2.908-.418C1.827-.418 1.172-1.43 1.172-2.434C1.172-3.466 1.89-4.435 2.908-4.435C3.368-4.435 3.843-4.289 4.163-4.045L4.275-4.679C3.787-4.861 3.396-4.917 2.887-4.917C1.506-4.917 .474-3.773 .474-2.427C.474-.99 1.569 .07 2.929 .07C3.612 .07 3.898-.07 4.359-.321L4.317-.851Z'/>
+<path id='g0-71' d='M4.442-2.085H2.88V-1.625H3.829V-.558C3.522-.481 3.222-.418 2.908-.418C1.834-.418 1.172-1.43 1.172-2.427C1.172-3.382 1.82-4.435 2.873-4.435C3.515-4.435 3.919-4.24 4.268-3.947L4.38-4.582C3.898-4.812 3.473-4.924 2.943-4.924C1.534-4.924 .474-3.822 .474-2.427C.474-1.067 1.527 .07 2.901 .07C3.403 .07 3.996-.042 4.442-.272V-2.085Z'/>
+<path id='g0-73' d='M1.381-4.84H.676V0H1.381V-4.84Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-85' d='M4.4-4.84H3.794V-1.625C3.794-.69 3.166-.265 2.566-.265S1.381-.697 1.381-1.618V-4.84H.676V-1.632C.676-.607 1.555 .146 2.559 .146C3.557 .146 4.4-.614 4.4-1.632V-4.84Z'/>
+<path id='g0-88' d='M2.755-2.552L4.519-4.84H3.759L2.413-3.055L1.039-4.84H.209L2.071-2.552L.105 0H.865L2.413-2.099L3.996 0H4.826L2.755-2.552Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-103' d='M3.508-3.166C3.354-3.166 2.887-3.159 2.357-2.957L2.343-2.95C2.092-3.117 1.848-3.166 1.646-3.166C.962-3.166 .453-2.629 .453-2.029C.453-1.785 .537-1.534 .697-1.339C.6-1.22 .495-1.025 .495-.76C.495-.488 .607-.314 .669-.23C.286-.007 .209 .314 .209 .481C.209 1.011 .941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 .481C3.487-.502 2.267-.502 1.967-.502H1.318C1.206-.502 .907-.502 .907-.865C.907-1.004 .955-1.074 .962-1.088C1.206-.934 1.451-.886 1.639-.886C2.322-.886 2.831-1.423 2.831-2.022C2.831-2.246 2.769-2.448 2.643-2.636C2.615-2.678 2.615-2.685 2.615-2.692C2.615-2.72 3.034-2.72 3.068-2.72C3.075-2.72 3.34-2.72 3.592-2.692L3.508-3.166ZM1.646-1.318C1.269-1.318 .99-1.555 .99-2.022C.99-2.566 1.339-2.734 1.639-2.734C2.015-2.734 2.294-2.497 2.294-2.029C2.294-1.485 1.946-1.318 1.646-1.318ZM1.974 .042C2.134 .042 2.957 .042 2.957 .488C2.957 .788 2.434 .997 1.848 .997S.739 .788 .739 .488C.739 .453 .739 .042 1.304 .042H1.974Z'/>
+<path id='g0-104' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.625-3.166 1.304-2.817 1.165-2.671V-4.84H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-106' d='M1.381-4.784H.676V-4.08H1.381V-4.784ZM-.453 1.186C-.133 1.36 .181 1.423 .446 1.423C.928 1.423 1.381 1.053 1.381 .411V-3.096H.795V.46C.795 .586 .795 .697 .649 .816C.488 .934 .293 .934 .23 .934C-.063 .934-.244 .802-.328 .725L-.453 1.186Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-117' d='M3.243-3.096H2.636V-1.074C2.636-.516 2.162-.342 1.757-.342C1.241-.342 1.186-.481 1.186-.802V-3.096H.579V-.76C.579-.139 .851 .07 1.339 .07C1.625 .07 2.239 .014 2.657-.321V0H3.243V-3.096Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+<path id='g0-122' d='M2.957-2.803V-3.096H.307V-2.65H1.332C1.416-2.65 1.499-2.657 1.583-2.657H2.127L.209-.307V0H2.978V-.467H1.897C1.813-.467 1.73-.46 1.646-.46H1.039L2.957-2.803Z'/>
+</defs>
+<g id='page4'>
+<path d='M194.617 260.785V251.93M253.285 260.785V251.93M311.953 260.785V251.93M370.625 260.785V251.93M429.293 260.785V251.93M194.617 75.308V84.164M253.285 75.308V84.164M311.953 75.308V84.164M370.625 75.308V84.164M429.293 75.308V84.164' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M165.281 256.18V251.93M223.953 256.18V251.93M282.621 256.18V251.93M341.289 256.18V251.93M399.957 256.18V251.93M458.629 256.18V251.93M165.281 79.91V84.164M223.953 79.91V84.164M282.621 79.91V84.164M341.289 79.91V84.164M399.957 79.91V84.164M458.629 79.91V84.164' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 251.93H140.199M135.949 218.375H140.199M135.949 184.824H140.199M135.949 151.269H140.199M135.949 117.719H140.199M135.949 84.164H140.199M487.961 251.93H483.711M487.961 218.375H483.711M487.961 184.824H483.711M487.961 151.269H483.711M487.961 117.719H483.711M487.961 84.164H483.711' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 251.93V84.164H487.961V251.93H135.949Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-97'/>
+<use x='172.353' y='191.334' xlink:href='#g3-108'/>
+<use x='174.373' y='191.334' xlink:href='#g3-108'/>
+<use x='176.393' y='191.334' xlink:href='#g3-111'/>
+<use x='180.863' y='191.334' xlink:href='#g3-99'/>
+<use x='184.627' y='191.334' xlink:href='#g3-45'/>
+<use x='187.449' y='191.334' xlink:href='#g3-116'/>
+<use x='190.507' y='191.334' xlink:href='#g3-101'/>
+<use x='194.271' y='191.334' xlink:href='#g3-115'/>
+<use x='197.517' y='191.334' xlink:href='#g3-116'/>
+<use x='200.575' y='191.334' xlink:href='#g3-49'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-97'/>
+<use x='172.353' y='191.334' xlink:href='#g3-108'/>
+<use x='174.373' y='191.334' xlink:href='#g3-108'/>
+<use x='176.393' y='191.334' xlink:href='#g3-111'/>
+<use x='180.863' y='191.334' xlink:href='#g3-99'/>
+<use x='184.627' y='191.334' xlink:href='#g3-45'/>
+<use x='187.449' y='191.334' xlink:href='#g3-116'/>
+<use x='190.507' y='191.334' xlink:href='#g3-101'/>
+<use x='194.271' y='191.334' xlink:href='#g3-115'/>
+<use x='197.517' y='191.334' xlink:href='#g3-116'/>
+<use x='200.575' y='191.334' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-115'/>
+<use x='171.531' y='191.334' xlink:href='#g3-104'/>
+<use x='175.904' y='191.334' xlink:href='#g3-54'/>
+<use x='180.138' y='191.334' xlink:href='#g3-98'/>
+<use x='184.746' y='191.334' xlink:href='#g3-101'/>
+<use x='188.509' y='191.334' xlink:href='#g3-110'/>
+<use x='192.882' y='191.334' xlink:href='#g3-99'/>
+<use x='196.646' y='191.334' xlink:href='#g3-104'/>
+<use x='201.018' y='191.334' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-115'/>
+<use x='171.531' y='191.334' xlink:href='#g3-104'/>
+<use x='175.904' y='191.334' xlink:href='#g3-56'/>
+<use x='180.138' y='191.334' xlink:href='#g3-98'/>
+<use x='184.746' y='191.334' xlink:href='#g3-101'/>
+<use x='188.509' y='191.334' xlink:href='#g3-110'/>
+<use x='192.882' y='191.334' xlink:href='#g3-99'/>
+<use x='196.646' y='191.334' xlink:href='#g3-104'/>
+<use x='201.018' y='191.334' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-120'/>
+<use x='172.187' y='191.334' xlink:href='#g3-109'/>
+<use x='178.912' y='191.334' xlink:href='#g3-97'/>
+<use x='182.98' y='191.334' xlink:href='#g3-108'/>
+<use x='185' y='191.334' xlink:href='#g3-108'/>
+<use x='187.02' y='191.334' xlink:href='#g3-111'/>
+<use x='191.49' y='191.334' xlink:href='#g3-99'/>
+<use x='195.254' y='191.334' xlink:href='#g3-45'/>
+<use x='198.076' y='191.334' xlink:href='#g3-116'/>
+<use x='201.134' y='191.334' xlink:href='#g3-101'/>
+<use x='204.898' y='191.334' xlink:href='#g3-115'/>
+<use x='208.144' y='191.334' xlink:href='#g3-116'/>
+<use x='211.202' y='191.334' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' y='191.334' xlink:href='#g3-99'/>
+<use x='172.049' y='191.334' xlink:href='#g3-97'/>
+<use x='176.117' y='191.334' xlink:href='#g3-99'/>
+<use x='179.88' y='191.334' xlink:href='#g3-104'/>
+<use x='184.253' y='191.334' xlink:href='#g3-101'/>
+<use x='188.017' y='191.334' xlink:href='#g3-45'/>
+<use x='190.839' y='191.334' xlink:href='#g3-115'/>
+<use x='194.086' y='191.334' xlink:href='#g3-99'/>
+<use x='197.849' y='191.334' xlink:href='#g3-114'/>
+<use x='200.741' y='191.334' xlink:href='#g3-97'/>
+<use x='204.81' y='191.334' xlink:href='#g3-116'/>
+<use x='207.868' y='191.334' xlink:href='#g3-99'/>
+<use x='211.631' y='191.334' xlink:href='#g3-104'/>
+<use x='216.004' y='191.334' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-53'/>
+<use x='175.048' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-53'/>
+<use x='175.048' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-53'/>
+<use x='175.048' y='191.334' xlink:href='#g2-120'/>
+</g>
+<path d='M135.949 184.824H487.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M140.125 251.93H143.363V184.824H140.125ZM198.797 251.93H202.035V184.824H198.797ZM257.465 251.93H260.703V184.824H257.465ZM316.133 251.93H319.371V184.824H316.133ZM374.801 251.93H378.039V184.824H374.801ZM433.473 251.93H436.711V184.824H433.473Z' fill='#933' clip-path='url(#clip4)'/>
+<path d='M140.125 251.93H143.363V184.824H140.125ZM198.797 251.93H202.035V184.824H198.797ZM257.465 251.93H260.703V184.824H257.465ZM316.133 251.93H319.371V184.824H316.133ZM374.801 251.93H378.039V184.824H374.801ZM433.473 251.93H436.711V184.824H433.473Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M141.746 184.824V184.758' fill='#933' clip-path='url(#clip4)'/>
+<path d='M141.746 184.824V184.758' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M139.754 184.758H143.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M141.746 184.824V184.891' fill='#933' clip-path='url(#clip4)'/>
+<path d='M141.746 184.824V184.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M143.738 184.891H139.754' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M200.414 184.824V184.621' fill='#933' clip-path='url(#clip4)'/>
+<path d='M200.414 184.824V184.621' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M198.422 184.621H202.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M200.414 184.824V185.023' fill='#933' clip-path='url(#clip4)'/>
+<path d='M200.414 184.824V185.023' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M202.406 185.023H198.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M259.082 184.824' fill='#933' clip-path='url(#clip4)'/>
+<path d='M257.09 184.824H261.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M259.082 184.824' fill='#933' clip-path='url(#clip4)'/>
+<path d='M257.09 184.824H261.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M317.754 184.824V178.785' fill='#933' clip-path='url(#clip4)'/>
+<path d='M317.754 184.824V178.785' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M315.762 178.785H319.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M317.754 184.824V190.863' fill='#933' clip-path='url(#clip4)'/>
+<path d='M317.754 184.824V190.863' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M319.746 190.864H315.758' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M376.422 184.824V184.086' fill='#933' clip-path='url(#clip4)'/>
+<path d='M376.422 184.824V184.086' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M374.43 184.086H378.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M376.422 184.824V185.562' fill='#933' clip-path='url(#clip4)'/>
+<path d='M376.422 184.824V185.562' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M378.414 185.562H374.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M435.09 184.824V181.402' fill='#933' clip-path='url(#clip4)'/>
+<path d='M435.09 184.824V181.402' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M433.098 181.403H437.082' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M435.09 184.824V188.246' fill='#933' clip-path='url(#clip4)'/>
+<path d='M435.09 184.824V188.246' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M437.082 188.246H433.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M145.356 251.93H148.594V184.488H145.356ZM204.028 251.93H207.266V184.621H204.028ZM262.695 251.93H265.934V184.824H262.695ZM321.363 251.93H324.602V182.004H321.363ZM380.031 251.93H383.27V178.648H380.031ZM438.703 251.93H441.942V187.238H438.703Z' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M145.356 251.93H148.594V184.488H145.356ZM204.028 251.93H207.266V184.621H204.028ZM262.695 251.93H265.934V184.824H262.695ZM321.363 251.93H324.602V182.004H321.363ZM380.031 251.93H383.27V178.648H380.031ZM438.703 251.93H441.942V187.238H438.703Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M146.977 184.488V184.422' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M146.977 184.488V184.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M144.984 184.421H148.968' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M146.977 184.488V184.555' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M146.977 184.488V184.555' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M148.968 184.555H144.984' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M205.645 184.621V184.555' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M205.645 184.621V184.555' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M203.652 184.555H207.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M205.645 184.621V184.687' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M205.645 184.621V184.687' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M207.636 184.688H203.652' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M264.313 184.824' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M262.32 184.824H266.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M264.313 184.824' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M262.32 184.824H266.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M322.984 182.004V177.441' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M322.984 182.004V177.441' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M320.992 177.441H324.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M322.984 182.004V186.566' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M322.984 182.004V186.566' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M324.976 186.567H320.988' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M381.652 178.648V176.973' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M381.652 178.648V176.973' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M379.66 176.973H383.644' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M381.652 178.648V180.328' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M381.652 178.648V180.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M383.644 180.328H379.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M440.32 187.238V181.402' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M440.32 187.238V181.402' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M438.328 181.403H442.312' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M440.32 187.238V193.078' fill='#bf8080' clip-path='url(#clip4)'/>
+<path d='M440.32 187.238V193.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M442.312 193.078H438.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M150.586 251.93H153.824V184.621H150.586ZM209.258 251.93H212.496V171.871H209.258ZM267.926 251.93H271.164V137.312H267.926ZM326.594 251.93H329.832V84.164H326.594ZM385.262 251.93H388.5V84.164H385.262ZM443.934 251.93H447.172V84.164H443.934Z' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M150.586 251.93H153.824V184.621H150.586ZM209.258 251.93H212.496V171.871H209.258ZM267.926 251.93H271.164V137.312H267.926ZM326.594 251.93H329.832V84.164H326.594ZM385.262 251.93H388.5V84.164H385.262ZM443.934 251.93H447.172V84.164H443.934Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M152.207 184.621' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M150.215 184.621H154.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M152.207 184.621' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M150.215 184.621H154.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M210.875 171.871V170.461' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M210.875 171.871V170.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M208.883 170.461H212.867' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M210.875 171.871V173.281' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M210.875 171.871V173.281' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M212.868 173.281H208.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M269.543 137.312V129.394' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M269.543 137.312V129.394' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M267.551 129.394H271.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M269.543 137.312V145.23' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M269.543 137.312V145.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M271.535 145.23H267.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M328.215 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M326.223 84.164H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M328.215 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M326.223 84.164H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M386.883 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M384.891 84.164H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M386.883 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M384.891 84.164H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M445.551 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M443.559 84.164H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M445.551 84.164' fill='#8080bf' clip-path='url(#clip4)'/>
+<path d='M443.559 84.164H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M155.817 251.93H159.055V179.926H155.817ZM214.488 251.93H217.727V180.461H214.488ZM273.156 251.93H276.395V131.676H273.156ZM331.824 251.93H335.063V126.105H331.824ZM390.492 251.93H393.731V84.164H390.492ZM449.164 251.93H452.402V84.164H449.164Z' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M155.817 251.93H159.055V179.926H155.817ZM214.488 251.93H217.727V180.461H214.488ZM273.156 251.93H276.395V131.676H273.156ZM331.824 251.93H335.063V126.105H331.824ZM390.492 251.93H393.731V84.164H390.492ZM449.164 251.93H452.402V84.164H449.164Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M157.438 179.926' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M155.445 179.925H159.429' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M157.438 179.926' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M155.445 179.925H159.429' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M216.106 180.461' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M214.113 180.461H218.097' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M216.106 180.461' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M214.113 180.461H218.097' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M274.774 131.676V127.715' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M274.774 131.676V127.715' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M272.781 127.715H276.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M274.774 131.676V135.633' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M274.774 131.676V135.633' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M276.765 135.633H272.781' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M333.445 126.105V120.066' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M333.445 126.105V120.066' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M331.453 120.067H335.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M333.445 126.105V132.144' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M333.445 126.105V132.144' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M335.437 132.145H331.449' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M392.113 84.164' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M390.121 84.164H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M392.113 84.164' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M390.121 84.164H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M450.781 84.164' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M448.789 84.164H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M450.781 84.164' fill='#ffb733' clip-path='url(#clip4)'/>
+<path d='M448.789 84.164H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M161.047 251.93H164.285V162.141H161.047ZM219.719 251.93H222.957V163.418H219.719ZM278.387 251.93H281.625V84.164H278.387ZM337.055 251.93H340.293V112.148H337.055ZM395.723 251.93H398.961V86.848H395.723ZM454.395 251.93H457.633V184.824H454.395Z' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M161.047 251.93H164.285V162.141H161.047ZM219.719 251.93H222.957V163.418H219.719ZM278.387 251.93H281.625V84.164H278.387ZM337.055 251.93H340.293V112.148H337.055ZM395.723 251.93H398.961V86.848H395.723ZM454.395 251.93H457.633V184.824H454.395Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M162.668 162.141V162.074' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M162.668 162.141V162.074' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M160.676 162.074H164.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M162.668 162.141V162.207' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M162.668 162.141V162.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M164.661 162.207H160.676' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M221.336 163.418V163.348' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M221.336 163.418V163.348' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M219.344 163.348H223.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M221.336 163.418V163.484' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M221.336 163.418V163.484' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M223.329 163.484H219.344' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M280.004 84.164' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M278.012 84.164H282' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M280.004 84.164' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M278.012 84.164H282' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M338.676 112.148' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M336.684 112.148H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M338.676 112.148' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M336.684 112.148H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M397.344 86.848V86.648' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M397.344 86.848V86.648' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M395.352 86.648H399.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M397.344 86.848V87.051' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M397.344 86.848V87.051' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M399.336 87.051H395.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M456.012 184.824V175.832' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M456.012 184.824V175.832' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M454.02 175.832H458.004' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M456.012 184.824V193.816' fill='#bf80bf' clip-path='url(#clip4)'/>
+<path d='M456.012 184.824V193.816' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M458.004 193.816H454.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M166.278 251.93H169.516V171.937H166.278ZM224.949 251.93H228.188V181.066H224.949ZM283.617 251.93H286.856V151.269H283.617ZM342.285 251.93H345.524V162.477H342.285ZM400.953 251.93H404.192V192.34H400.953ZM459.625 251.93H462.863V189.586H459.625Z' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M166.278 251.93H169.516V171.937H166.278ZM224.949 251.93H228.188V181.066H224.949ZM283.617 251.93H286.856V151.269H283.617ZM342.285 251.93H345.524V162.477H342.285ZM400.953 251.93H404.192V192.34H400.953ZM459.625 251.93H462.863V189.586H459.625Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M167.899 171.937' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M165.906 171.938H169.89' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M167.899 171.937' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M165.906 171.938H169.89' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M226.567 181.066V180.996' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M226.567 181.066V180.996' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M224.574 180.996H228.558' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M226.567 181.066V181.133' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M226.567 181.066V181.133' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M228.559 181.133H224.574' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M285.234 151.269' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M283.242 151.27H287.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M285.234 151.269' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M283.242 151.27H287.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M343.906 162.477V160.195' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M343.906 162.477V160.195' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M341.914 160.195H345.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M343.906 162.477V164.758' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M343.906 162.477V164.758' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M345.898 164.758H341.91' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M402.574 192.34V191.266' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M402.574 192.34V191.266' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M400.582 191.265H404.566' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M402.574 192.34V193.414' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M402.574 192.34V193.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M404.566 193.414H400.582' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M461.242 189.586V186.164' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M461.242 189.586V186.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M459.25 186.164H463.234' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M461.242 189.586V193.012' fill='#c96' clip-path='url(#clip4)'/>
+<path d='M461.242 189.586V193.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M463.234 193.012H459.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M171.508 251.93H174.746V180.93H171.508ZM230.18 251.93H233.414V179.051H230.18ZM288.848 251.93H292.086V84.164H288.848ZM347.516 251.93H350.754V84.164H347.516ZM406.184 251.93H409.422V84.164H406.184ZM464.856 251.93H468.094V84.164H464.856Z' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M171.508 251.93H174.746V180.93H171.508ZM230.18 251.93H233.414V179.051H230.18ZM288.848 251.93H292.086V84.164H288.848ZM347.516 251.93H350.754V84.164H347.516ZM406.184 251.93H409.422V84.164H406.184ZM464.856 251.93H468.094V84.164H464.856Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M173.129 180.93' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M171.137 180.93H175.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M173.129 180.93' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M171.137 180.93H175.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M231.797 179.051V178.852' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M231.797 179.051V178.852' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M229.805 178.852H233.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M231.797 179.051V179.254' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M231.797 179.051V179.254' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M233.79 179.254H229.805' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M290.465 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M288.473 84.164H292.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M290.465 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M288.473 84.164H292.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M349.137 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M347.145 84.164H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M349.137 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M347.145 84.164H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M407.805 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M405.813 84.164H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M407.805 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M405.813 84.164H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M466.473 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M464.481 84.164H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M466.473 84.164' fill='#80bf80' clip-path='url(#clip4)'/>
+<path d='M464.481 84.164H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M176.738 251.93H179.977V154.828H176.738ZM235.41 251.93H238.645V176.168H235.41ZM294.078 251.93H297.317V84.164H294.078ZM352.746 251.93H355.984V84.164H352.746ZM411.414 251.93H414.652V84.164H411.414ZM470.086 251.93H473.324V189.586H470.086Z' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M176.738 251.93H179.977V154.828H176.738ZM235.41 251.93H238.645V176.168H235.41ZM294.078 251.93H297.317V84.164H294.078ZM352.746 251.93H355.984V84.164H352.746ZM411.414 251.93H414.652V84.164H411.414ZM470.086 251.93H473.324V189.586H470.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M178.36 154.828V148.922' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M178.36 154.828V148.922' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M176.367 148.922H180.351' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M178.36 154.828V160.73' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M178.36 154.828V160.73' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M180.352 160.731H176.367' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M237.027 176.168V175.832' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M237.027 176.168V175.832' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M235.035 175.832H239.019' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M237.027 176.168V176.5' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M237.027 176.168V176.5' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M239.02 176.5H235.035' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M295.695 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M293.703 84.164H297.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M295.695 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M293.703 84.164H297.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M354.367 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M352.375 84.164H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M354.367 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M352.375 84.164H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M413.035 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M411.043 84.164H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M413.035 84.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M411.043 84.164H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M471.703 189.586V186.164' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M471.703 189.586V186.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M469.711 186.164H473.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M471.703 189.586V193.012' fill='#bfbf80' clip-path='url(#clip4)'/>
+<path d='M471.703 189.586V193.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M473.695 193.012H469.711' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M181.969 251.93H185.207V167.914H181.969ZM240.641 251.93H243.875V168.984H240.641ZM299.309 251.93H302.547V84.164H299.309ZM357.977 251.93H361.215V84.164H357.977ZM416.645 251.93H419.883V84.164H416.645ZM475.317 251.93H478.555V84.164H475.317Z' fill='#399' clip-path='url(#clip4)'/>
+<path d='M181.969 251.93H185.207V167.914H181.969ZM240.641 251.93H243.875V168.984H240.641ZM299.309 251.93H302.547V84.164H299.309ZM357.977 251.93H361.215V84.164H357.977ZM416.645 251.93H419.883V84.164H416.645ZM475.317 251.93H478.555V84.164H475.317Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M183.59 167.914V167.844' fill='#399' clip-path='url(#clip4)'/>
+<path d='M183.59 167.914V167.844' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M181.598 167.844H185.583' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M183.59 167.914V167.98' fill='#399' clip-path='url(#clip4)'/>
+<path d='M183.59 167.914V167.98' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M185.582 167.98H181.597' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M242.258 168.984V168.918' fill='#399' clip-path='url(#clip4)'/>
+<path d='M242.258 168.984V168.918' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M240.266 168.918H244.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M242.258 168.984V169.055' fill='#399' clip-path='url(#clip4)'/>
+<path d='M242.258 168.984V169.055' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M244.25 169.055H240.265' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M300.926 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M298.933 84.164H302.921' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M300.926 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M298.933 84.164H302.921' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M359.598 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M357.606 84.164H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M359.598 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M357.606 84.164H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M418.266 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M416.274 84.164H420.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M418.266 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M416.274 84.164H420.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M476.934 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M474.942 84.164H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M476.934 84.164' fill='#399' clip-path='url(#clip4)'/>
+<path d='M474.942 84.164H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M187.199 251.93H190.438V175.562H187.199ZM245.871 251.93H249.106V176.168H245.871ZM304.539 251.93H307.777V92.551H304.539ZM363.207 251.93H366.445V126.105H363.207ZM421.875 251.93H425.113V109.461H421.875ZM480.547 251.93H483.785V175.227H480.547Z' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M187.199 251.93H190.438V175.562H187.199ZM245.871 251.93H249.106V176.168H245.871ZM304.539 251.93H307.777V92.551H304.539ZM363.207 251.93H366.445V126.105H363.207ZM421.875 251.93H425.113V109.461H421.875ZM480.547 251.93H483.785V175.227H480.547Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M188.82 175.562V175.43' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M188.82 175.562V175.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M186.828 175.43H190.813' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M188.82 175.562V175.695' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M188.82 175.562V175.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M190.813 175.696H186.828' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M247.488 176.168V175.965' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M247.488 176.168V175.965' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M245.496 175.965H249.481' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M247.488 176.168V176.367' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M247.488 176.168V176.367' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M249.481 176.368H245.496' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M306.156 92.551V74.433' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M306.156 92.551V74.433' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M304.164 74.434H308.152' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M306.156 92.551V110.672' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M306.156 92.551V110.672' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M308.149 110.672H304.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M364.828 126.105V123.824' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M364.828 126.105V123.824' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M362.836 123.825H366.82' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M364.828 126.105V128.387' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M364.828 126.105V128.387' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M366.82 128.387H362.832' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M423.496 109.461V109.262' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M423.496 109.461V109.262' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M421.504 109.262H425.488' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M423.496 109.461V109.664' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M423.496 109.461V109.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M425.488 109.664H421.504' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M482.164 175.227V171.805' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M482.164 175.227V171.805' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M480.172 171.804H484.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M482.164 175.227V178.648' fill='#d9b3b3' clip-path='url(#clip4)'/>
+<path d='M482.164 175.227V178.648' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M484.156 178.648H480.172' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<path d='M369.781 314.227H487.762V278.973H369.781Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip4)'/>
+<g transform='matrix(1 0 0 1 204.818 118.327)'>
+<use x='168.285' y='167.424' xlink:href='#g2-99'/>
+<use x='170.637' y='167.424' xlink:href='#g2-53'/>
+<use x='173.284' y='167.424' xlink:href='#g2-45'/>
+<use x='175.048' y='167.424' xlink:href='#g2-49'/>
+<use x='177.694' y='167.424' xlink:href='#g2-56'/>
+<use x='180.341' y='167.424' xlink:href='#g2-120'/>
+<use x='182.779' y='167.424' xlink:href='#g2-108'/>
+<use x='184.042' y='167.424' xlink:href='#g2-97'/>
+<use x='186.438' y='167.424' xlink:href='#g2-114'/>
+<use x='188.245' y='167.424' xlink:href='#g2-103'/>
+<use x='190.891' y='167.424' xlink:href='#g2-101'/>
+<use x='193.244' y='167.424' xlink:href='#g2-44'/>
+<use x='196.478' y='167.424' xlink:href='#g2-49'/>
+<use x='199.124' y='167.424' xlink:href='#g2-52'/>
+<use x='201.771' y='167.424' xlink:href='#g2-52'/>
+<use x='204.417' y='167.424' xlink:href='#g2-71'/>
+<use x='207.946' y='167.424' xlink:href='#g2-98'/>
+<use x='168.285' y='173.401' xlink:href='#g2-50'/>
+<use x='170.931' y='173.401' xlink:href='#g4-2'/>
+<use x='178.092' y='173.401' xlink:href='#g2-49'/>
+<use x='180.738' y='173.401' xlink:href='#g2-56'/>
+<use x='183.385' y='173.401' xlink:href='#g2-45'/>
+<use x='185.149' y='173.401' xlink:href='#g2-99'/>
+<use x='187.501' y='173.401' xlink:href='#g2-111'/>
+<use x='190.001' y='173.401' xlink:href='#g2-114'/>
+<use x='191.808' y='173.401' xlink:href='#g2-101'/>
+<use x='195.925' y='173.401' xlink:href='#g2-73'/>
+<use x='197.395' y='173.401' xlink:href='#g2-110'/>
+<use x='200.128' y='173.401' xlink:href='#g2-116'/>
+<use x='202.039' y='173.401' xlink:href='#g2-101'/>
+<use x='204.391' y='173.401' xlink:href='#g2-108'/>
+<use x='207.418' y='173.401' xlink:href='#g2-88'/>
+<use x='210.947' y='173.401' xlink:href='#g2-101'/>
+<use x='213.299' y='173.401' xlink:href='#g2-111'/>
+<use x='215.945' y='173.401' xlink:href='#g2-110'/>
+<use x='220.442' y='173.401' xlink:href='#g2-64'/>
+<use x='223.971' y='173.401' xlink:href='#g2-51'/>
+<use x='226.617' y='173.401' xlink:href='#g2-71'/>
+<use x='230.146' y='173.401' xlink:href='#g2-104'/>
+<use x='232.879' y='173.401' xlink:href='#g2-122'/>
+<use x='168.285' y='179.379' xlink:href='#g2-85'/>
+<use x='171.917' y='179.379' xlink:href='#g2-98'/>
+<use x='174.65' y='179.379' xlink:href='#g2-117'/>
+<use x='177.383' y='179.379' xlink:href='#g2-110'/>
+<use x='180.116' y='179.379' xlink:href='#g2-116'/>
+<use x='182.027' y='179.379' xlink:href='#g2-117'/>
+<use x='186.524' y='179.379' xlink:href='#g2-50'/>
+<use x='189.17' y='179.379' xlink:href='#g2-48'/>
+<use x='191.817' y='179.379' xlink:href='#g2-46'/>
+<use x='193.287' y='179.379' xlink:href='#g2-48'/>
+<use x='195.933' y='179.379' xlink:href='#g2-52'/>
+<use x='198.58' y='179.379' xlink:href='#g2-44'/>
+<use x='201.814' y='179.379' xlink:href='#g2-71'/>
+<use x='205.343' y='179.379' xlink:href='#g2-67'/>
+<use x='208.724' y='179.379' xlink:href='#g2-67'/>
+<use x='213.87' y='179.379' xlink:href='#g2-57'/>
+<use x='216.516' y='179.379' xlink:href='#g2-46'/>
+<use x='217.986' y='179.379' xlink:href='#g2-51'/>
+<use x='220.633' y='179.379' xlink:href='#g2-46'/>
+<use x='222.103' y='179.379' xlink:href='#g2-48'/>
+<use x='224.749' y='179.379' xlink:href='#g2-44'/>
+<use x='227.984' y='179.379' xlink:href='#g2-103'/>
+<use x='230.63' y='179.379' xlink:href='#g2-108'/>
+<use x='231.893' y='179.379' xlink:href='#g2-105'/>
+<use x='233.155' y='179.379' xlink:href='#g2-98'/>
+<use x='236.035' y='179.379' xlink:href='#g2-99'/>
+<use x='240.152' y='179.379' xlink:href='#g2-50'/>
+<use x='242.798' y='179.379' xlink:href='#g2-46'/>
+<use x='244.268' y='179.379' xlink:href='#g2-51'/>
+<use x='246.915' y='179.379' xlink:href='#g2-49'/>
+<use x='249.561' y='179.379' xlink:href='#g2-44'/>
+<use x='252.796' y='179.379' xlink:href='#g2-99'/>
+<use x='255.148' y='179.379' xlink:href='#g2-108'/>
+<use x='256.41' y='179.379' xlink:href='#g2-97'/>
+<use x='258.953' y='179.379' xlink:href='#g2-110'/>
+<use x='261.686' y='179.379' xlink:href='#g2-103'/>
+<use x='266.097' y='179.379' xlink:href='#g2-49'/>
+<use x='268.743' y='179.379' xlink:href='#g2-48'/>
+<use x='271.389' y='179.379' xlink:href='#g2-46'/>
+<use x='272.859' y='179.379' xlink:href='#g2-48'/>
+<use x='275.506' y='179.379' xlink:href='#g2-46'/>
+<use x='276.976' y='179.379' xlink:href='#g2-48'/>
+<use x='168.285' y='185.357' xlink:href='#g2-55'/>
+<use x='170.931' y='185.357' xlink:href='#g2-50'/>
+<use x='175.342' y='185.357' xlink:href='#g2-108'/>
+<use x='176.604' y='185.357' xlink:href='#g2-111'/>
+<use x='179.251' y='185.357' xlink:href='#g2-103'/>
+<use x='181.897' y='185.357' xlink:href='#g2-105'/>
+<use x='183.16' y='185.357' xlink:href='#g2-99'/>
+<use x='185.512' y='185.357' xlink:href='#g2-97'/>
+<use x='188.055' y='185.357' xlink:href='#g2-108'/>
+<use x='191.082' y='185.357' xlink:href='#g2-99'/>
+<use x='193.434' y='185.357' xlink:href='#g2-111'/>
+<use x='195.933' y='185.357' xlink:href='#g2-114'/>
+<use x='197.741' y='185.357' xlink:href='#g2-101'/>
+<use x='200.093' y='185.357' xlink:href='#g2-115'/>
+<use x='203.886' y='185.357' xlink:href='#g2-111'/>
+<use x='206.533' y='185.357' xlink:href='#g2-110'/>
+<use x='211.03' y='185.357' xlink:href='#g2-50'/>
+<use x='215.44' y='185.357' xlink:href='#g2-110'/>
+<use x='218.173' y='185.357' xlink:href='#g2-117'/>
+<use x='220.906' y='185.357' xlink:href='#g2-109'/>
+<use x='225.109' y='185.357' xlink:href='#g2-97'/>
+<use x='229.416' y='185.357' xlink:href='#g2-110'/>
+<use x='232.149' y='185.357' xlink:href='#g2-111'/>
+<use x='234.942' y='185.357' xlink:href='#g2-100'/>
+<use x='237.675' y='185.357' xlink:href='#g2-101'/>
+<use x='240.027' y='185.357' xlink:href='#g2-115'/>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-48'/>
+<use x='173.578' y='191.334' xlink:href='#g2-50'/>
+<use x='176.224' y='191.334' xlink:href='#g2-49'/>
+<use x='178.87' y='191.334' xlink:href='#g2-45'/>
+<use x='180.635' y='191.334' xlink:href='#g2-48'/>
+<use x='183.281' y='191.334' xlink:href='#g2-49'/>
+<use x='185.927' y='191.334' xlink:href='#g2-45'/>
+<use x='187.692' y='191.334' xlink:href='#g2-51'/>
+<use x='190.338' y='191.334' xlink:href='#g2-48'/>
+<use x='192.984' y='191.334' xlink:href='#g2-41'/>
+</g>
+<g transform='matrix(0 -1 1 0 -47.954 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 10.715 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 69.384 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 128.053 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 186.722 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 245.391 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -42.724 346.568)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 15.945 346.703)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.614 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.283 344.086)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 191.952 340.73)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 250.621 349.32)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-57'/>
+<use x='175.048' y='191.334' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -37.493 346.703)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.176 333.952)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.845 299.393)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-55'/>
+<use x='175.048' y='191.334' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.514 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-49'/>
+<use x='176.558' y='191.334' xlink:href='#g2-53'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-49'/>
+<use x='183.321' y='191.334' xlink:href='#g2-56'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.183 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-51'/>
+<use x='176.558' y='191.334' xlink:href='#g2-56'/>
+<use x='179.205' y='191.334' xlink:href='#g2-48'/>
+<use x='181.851' y='191.334' xlink:href='#g2-46'/>
+<use x='183.321' y='191.334' xlink:href='#g2-49'/>
+<use x='185.968' y='191.334' xlink:href='#g2-57'/>
+<use x='188.614' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 255.852 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-49'/>
+<use x='176.558' y='191.334' xlink:href='#g2-55'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-48'/>
+<use x='183.321' y='191.334' xlink:href='#g2-55'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.263 342.005)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.406 342.542)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.075 293.756)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-55'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.744 288.186)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-56'/>
+<use x='175.048' y='191.334' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.413 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-49'/>
+<use x='176.558' y='191.334' xlink:href='#g2-49'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-54'/>
+<use x='183.321' y='191.334' xlink:href='#g2-55'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.082 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-49'/>
+<use x='176.558' y='191.334' xlink:href='#g2-55'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-50'/>
+<use x='183.321' y='191.334' xlink:href='#g2-53'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -27.032 324.222)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-51'/>
+<use x='175.048' y='191.334' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.637 325.497)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-51'/>
+<use x='175.048' y='191.334' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.306 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-53'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-50'/>
+<use x='180.675' y='191.334' xlink:href='#g2-57'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 148.975 274.228)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.644 248.929)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-52'/>
+<use x='175.048' y='191.334' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 266.313 346.904)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -21.802 334.02)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.867 343.146)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.536 313.351)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-53'/>
+<use x='175.048' y='191.334' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 154.205 324.558)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-51'/>
+<use x='175.048' y='191.334' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.874 354.42)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-56'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 271.543 351.668)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-57'/>
+<use x='175.048' y='191.334' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.571 343.012)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 42.098 341.133)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-48'/>
+<use x='175.048' y='191.334' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.767 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-55'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-50'/>
+<use x='180.675' y='191.334' xlink:href='#g2-53'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.436 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-51'/>
+<use x='176.558' y='191.334' xlink:href='#g2-54'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-54'/>
+<use x='183.321' y='191.334' xlink:href='#g2-53'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 218.105 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-51'/>
+<use x='176.558' y='191.334' xlink:href='#g2-56'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-53'/>
+<use x='183.321' y='191.334' xlink:href='#g2-51'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 276.774 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-49'/>
+<use x='176.558' y='191.334' xlink:href='#g2-50'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-56'/>
+<use x='183.321' y='191.334' xlink:href='#g2-50'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -11.341 316.908)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-52'/>
+<use x='175.048' y='191.334' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 47.328 338.247)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 105.997 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-55'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-49'/>
+<use x='180.675' y='191.334' xlink:href='#g2-50'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 164.666 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-55'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-50'/>
+<use x='180.675' y='191.334' xlink:href='#g2-53'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 223.335 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-53'/>
+<use x='176.558' y='191.334' xlink:href='#g2-55'/>
+<use x='179.205' y='191.334' xlink:href='#g2-46'/>
+<use x='180.675' y='191.334' xlink:href='#g2-52'/>
+<use x='183.321' y='191.334' xlink:href='#g2-53'/>
+<use x='185.968' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 282.004 351.668)'>
+<use x='168.285' y='191.334' xlink:href='#g2-48'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-57'/>
+<use x='175.048' y='191.334' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -6.111 329.993)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-50'/>
+<use x='175.048' y='191.334' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 52.558 331.067)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-50'/>
+<use x='175.048' y='191.334' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 111.227 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-53'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-52'/>
+<use x='180.675' y='191.334' xlink:href='#g2-54'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 169.896 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-52'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-50'/>
+<use x='180.675' y='191.334' xlink:href='#g2-54'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 228.565 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-53'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-53'/>
+<use x='180.675' y='191.334' xlink:href='#g2-54'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 287.234 246.245)'>
+<use x='163.396' y='191.334' xlink:href='#g4-1'/>
+<use x='166.901' y='191.334' xlink:href='#g4-1'/>
+<use x='170.407' y='191.334' xlink:href='#g4-1'/>
+<use x='173.912' y='191.334' xlink:href='#g2-54'/>
+<use x='176.558' y='191.334' xlink:href='#g2-46'/>
+<use x='178.029' y='191.334' xlink:href='#g2-48'/>
+<use x='180.675' y='191.334' xlink:href='#g2-55'/>
+<use x='183.321' y='191.334' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -.88 337.643)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 57.789 338.247)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 116.458 254.633)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-51'/>
+<use x='175.048' y='191.334' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 175.127 288.186)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-56'/>
+<use x='175.048' y='191.334' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 233.796 271.544)'>
+<use x='168.285' y='191.334' xlink:href='#g2-50'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 292.465 337.308)'>
+<use x='168.285' y='191.334' xlink:href='#g2-49'/>
+<use x='170.931' y='191.334' xlink:href='#g2-46'/>
+<use x='172.401' y='191.334' xlink:href='#g2-49'/>
+<use x='175.048' y='191.334' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 -78.176 391.591)'>
+<use x='168.285' y='191.334' xlink:href='#g1-82'/>
+<use x='174.255' y='191.334' xlink:href='#g1-101'/>
+<use x='178.351' y='191.334' xlink:href='#g1-108'/>
+<use x='180.551' y='191.334' xlink:href='#g1-97'/>
+<use x='184.979' y='191.334' xlink:href='#g1-116'/>
+<use x='188.307' y='191.334' xlink:href='#g1-105'/>
+<use x='190.507' y='191.334' xlink:href='#g1-118'/>
+<use x='194.755' y='191.334' xlink:href='#g1-101'/>
+<use x='201.922' y='191.334' xlink:href='#g1-116'/>
+<use x='205.25' y='191.334' xlink:href='#g1-105'/>
+<use x='207.45' y='191.334' xlink:href='#g1-109'/>
+<use x='214.77' y='191.334' xlink:href='#g1-101'/>
+<use x='221.937' y='191.334' xlink:href='#g3-40'/>
+<use x='225.231' y='191.334' xlink:href='#g3-108'/>
+<use x='227.251' y='191.334' xlink:href='#g3-111'/>
+<use x='231.25' y='191.334' xlink:href='#g3-119'/>
+<use x='236.799' y='191.334' xlink:href='#g3-101'/>
+<use x='240.562' y='191.334' xlink:href='#g3-114'/>
+<use x='246.277' y='191.334' xlink:href='#g3-105'/>
+<use x='248.297' y='191.334' xlink:href='#g3-115'/>
+<use x='254.366' y='191.334' xlink:href='#g3-98'/>
+<use x='258.974' y='191.334' xlink:href='#g3-101'/>
+<use x='262.738' y='191.334' xlink:href='#g3-116'/>
+<use x='265.796' y='191.334' xlink:href='#g3-116'/>
+<use x='268.854' y='191.334' xlink:href='#g3-101'/>
+<use x='272.618' y='191.334' xlink:href='#g3-114'/>
+<use x='275.51' y='191.334' xlink:href='#g3-41'/>
+</g>
+<path d='M136.149 312.324H346.746V282.324H136.149Z' fill='#fff'/>
+<path d='M136.149 312.324H346.746V282.324H136.149Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' fill='#933'/>
+<path d='M139.336 292.816H142.324V284.844H139.336ZM145.313 292.816H148.301V286.836H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='191.843' y='178.327' xlink:href='#g3-120'/>
+<use x='195.745' y='178.327' xlink:href='#g3-109'/>
+<use x='202.47' y='178.327' xlink:href='#g3-105'/>
+<use x='204.49' y='178.327' xlink:href='#g3-58'/>
+<use x='206.843' y='178.327' xlink:href='#g0-57'/>
+<use x='210.548' y='178.327' xlink:href='#g0-52'/>
+</g>
+<path d='M177.086 292.816H180.074V284.844H177.086ZM183.063 292.816H186.055V286.836H183.063Z' fill='#bf8080'/>
+<path d='M177.086 292.816H180.074V284.844H177.086ZM183.063 292.816H186.055V286.836H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -38.403 114.479)'>
+<use x='233.123' y='178.327' xlink:href='#g3-109'/>
+<use x='239.848' y='178.327' xlink:href='#g3-105'/>
+<use x='241.869' y='178.327' xlink:href='#g3-58'/>
+<use x='244.221' y='178.327' xlink:href='#g0-56'/>
+<use x='247.926' y='178.327' xlink:href='#g0-57'/>
+</g>
+<path d='M221.895 292.816H224.883V284.844H221.895ZM227.875 292.816H230.863V286.836H227.875Z' fill='#8080bf'/>
+<path d='M221.895 292.816H224.883V284.844H221.895ZM227.875 292.816H230.863V286.836H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='277.134' y='178.327' xlink:href='#g3-116'/>
+<use x='280.192' y='178.327' xlink:href='#g3-99'/>
+<use x='283.956' y='178.327' xlink:href='#g3-58'/>
+<use x='286.308' y='178.327' xlink:href='#g0-53'/>
+<use x='290.013' y='178.327' xlink:href='#g0-56'/>
+</g>
+<path d='M265.109 292.816H268.098V284.844H265.109ZM271.086 292.816H274.074V286.836H271.086Z' fill='#ffb733'/>
+<path d='M265.109 292.816H268.098V284.844H265.109ZM271.086 292.816H274.074V286.836H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='319.615' y='178.327' xlink:href='#g3-106'/>
+<use x='321.871' y='178.327' xlink:href='#g3-101'/>
+<use x='325.634' y='178.327' xlink:href='#g3-58'/>
+<use x='327.987' y='178.327' xlink:href='#g0-53'/>
+<use x='331.691' y='178.327' xlink:href='#g0-56'/>
+</g>
+<path d='M306.859 292.816H309.848V284.844H306.859ZM312.836 292.816H315.824V286.836H312.836Z' fill='#bf80bf'/>
+<path d='M306.859 292.816H309.848V284.844H306.859ZM312.836 292.816H315.824V286.836H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='359.038' y='178.327' xlink:href='#g3-116'/>
+<use x='362.096' y='178.327' xlink:href='#g3-98'/>
+<use x='366.469' y='178.327' xlink:href='#g3-98'/>
+<use x='370.842' y='178.327' xlink:href='#g3-58'/>
+<use x='373.194' y='178.327' xlink:href='#g0-53'/>
+<use x='376.899' y='178.327' xlink:href='#g0-48'/>
+</g>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' fill='#c96'/>
+<path d='M139.336 305.82H142.324V297.852H139.336ZM145.313 305.82H148.301V299.844H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='191.843' y='191.334' xlink:href='#g3-114'/>
+<use x='194.735' y='191.334' xlink:href='#g3-112'/>
+<use x='199.108' y='191.334' xlink:href='#g3-58'/>
+<use x='201.46' y='191.334' xlink:href='#g0-55'/>
+<use x='205.165' y='191.334' xlink:href='#g0-53'/>
+</g>
+<path d='M177.086 305.82H180.074V297.852H177.086ZM183.063 305.82H186.055V299.844H183.063Z' fill='#80bf80'/>
+<path d='M177.086 305.82H180.074V297.852H177.086ZM183.063 305.82H186.055V299.844H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='233.123' y='191.334' xlink:href='#g3-104'/>
+<use x='237.496' y='191.334' xlink:href='#g3-111'/>
+<use x='241.73' y='191.334' xlink:href='#g3-97'/>
+<use x='245.563' y='191.334' xlink:href='#g3-114'/>
+<use x='248.455' y='191.334' xlink:href='#g3-100'/>
+<use x='252.828' y='191.334' xlink:href='#g3-58'/>
+<use x='255.18' y='191.334' xlink:href='#g0-51'/>
+<use x='258.885' y='191.334' xlink:href='#g0-56'/>
+</g>
+<path d='M221.895 305.82H224.883V297.852H221.895ZM227.875 305.82H230.863V299.844H227.875Z' fill='#bfbf80'/>
+<path d='M221.895 305.82H224.883V297.852H221.895ZM227.875 305.82H230.863V299.844H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='277.134' y='191.334' xlink:href='#g3-109'/>
+<use x='283.859' y='191.334' xlink:href='#g3-101'/>
+<use x='287.622' y='191.334' xlink:href='#g3-115'/>
+<use x='290.869' y='191.334' xlink:href='#g3-104'/>
+<use x='295.241' y='191.334' xlink:href='#g3-58'/>
+<use x='297.593' y='191.334' xlink:href='#g0-51'/>
+<use x='301.298' y='191.334' xlink:href='#g0-54'/>
+</g>
+<path d='M265.109 305.82H268.098V297.852H265.109ZM271.086 305.82H274.074V299.844H271.086Z' fill='#399'/>
+<path d='M265.109 305.82H268.098V297.852H265.109ZM271.086 305.82H274.074V299.844H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='319.615' y='191.334' xlink:href='#g3-103'/>
+<use x='323.849' y='191.334' xlink:href='#g3-108'/>
+<use x='325.869' y='191.334' xlink:href='#g3-105'/>
+<use x='327.89' y='191.334' xlink:href='#g3-98'/>
+<use x='332.498' y='191.334' xlink:href='#g3-99'/>
+<use x='336.261' y='191.334' xlink:href='#g3-58'/>
+<use x='338.614' y='191.334' xlink:href='#g0-52'/>
+<use x='342.318' y='191.334' xlink:href='#g0-54'/>
+</g>
+<path d='M306.859 305.82H309.848V297.852H306.859ZM312.836 305.82H315.824V299.844H312.836Z' fill='#d9b3b3'/>
+<path d='M306.859 305.82H309.848V297.852H306.859ZM312.836 305.82H315.824V299.844H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='359.038' y='191.334' xlink:href='#g3-115'/>
+<use x='362.285' y='191.334' xlink:href='#g3-109'/>
+<use x='369.009' y='191.334' xlink:href='#g3-105'/>
+<use x='371.03' y='191.334' xlink:href='#g3-58'/>
+<use x='373.382' y='191.334' xlink:href='#g0-53'/>
+<use x='377.087' y='191.334' xlink:href='#g0-57'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg b/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg
new file mode 100644 (file)
index 0000000..6cd36aa
--- /dev/null
@@ -0,0 +1,836 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.628pt' height='207.789pt' viewBox='52.934 54.993 381.628 207.789'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip1'>
+<path d='M82.148 246.637H434.164V78.871H82.148Z'/>
+</clipPath>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-114' d='M1.462-1.91C1.462-2.851 2.197-3.425 3.013-3.434V-4.08C2.367-4.071 1.775-3.748 1.408-3.219V-4.035H.744V0H1.462V-1.91Z'/>
+<path id='g1-115' d='M3.165-3.847C2.609-4.098 2.197-4.133 1.829-4.133C1.623-4.133 .305-4.133 .305-2.95C.305-2.52 .565-2.251 .664-2.152C1.004-1.856 1.237-1.811 1.847-1.695C2.134-1.641 2.645-1.542 2.645-1.085C2.645-.502 1.919-.502 1.802-.502C1.273-.502 .762-.681 .377-.95L.26-.296C.798-.009 1.345 .099 1.802 .099C2.385 .099 3.318-.09 3.318-1.157C3.318-1.47 3.192-1.784 2.878-2.053C2.573-2.313 2.304-2.367 1.748-2.475C1.426-2.537 .977-2.618 .977-3.04C.977-3.569 1.614-3.569 1.748-3.569C2.403-3.569 2.789-3.362 3.049-3.219L3.165-3.847Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-102' xlink:href='#g0-102' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-102' d='M1.325-2.657H2.12V-3.096H1.304V-3.898C1.304-4.38 1.743-4.449 1.974-4.449C2.12-4.449 2.308-4.428 2.566-4.331V-4.84C2.385-4.882 2.169-4.91 1.981-4.91C1.262-4.91 .739-4.394 .739-3.703V-3.096H.202V-2.657H.739V0H1.325V-2.657Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+</defs>
+<g id='page1'>
+<path d='M140.82 255.492V246.637M199.488 255.492V246.637M258.156 255.492V246.637M316.824 255.492V246.637M375.496 255.492V246.637M140.82 70.016V78.871M199.488 70.016V78.871M258.156 70.016V78.871M316.824 70.016V78.871M375.496 70.016V78.871' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M111.484 250.887V246.637M170.152 250.887V246.637M228.824 250.887V246.637M287.492 250.887V246.637M346.16 250.887V246.637M404.828 250.887V246.637M111.484 74.617V78.871M170.152 74.617V78.871M228.824 74.617V78.871M287.492 74.617V78.871M346.16 74.617V78.871M404.828 74.617V78.871' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 246.637H86.402M82.148 213.082H86.402M82.148 179.531H86.402M82.148 145.977H86.402M82.148 112.426H86.402M82.148 78.871H86.402M434.164 246.637H429.91M434.164 213.082H429.91M434.164 179.531H429.91M434.164 145.977H429.91M434.164 112.426H429.91M434.164 78.871H429.91' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 246.637V78.871H434.164V246.637H82.148Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -11.54 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-99'/>
+<use x='118.25' y='226.079' xlink:href='#g3-102'/>
+<use x='120.838' y='226.079' xlink:href='#g3-114'/>
+<use x='123.73' y='226.079' xlink:href='#g3-97'/>
+<use x='127.798' y='226.079' xlink:href='#g3-99'/>
+</g>
+<g transform='matrix(1 0 0 1 45.565 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-108'/>
+<use x='116.507' y='226.079' xlink:href='#g3-101'/>
+<use x='120.271' y='226.079' xlink:href='#g3-97'/>
+<use x='124.339' y='226.079' xlink:href='#g3-110'/>
+<use x='128.711' y='226.079' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 106.188 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-114'/>
+<use x='117.379' y='226.079' xlink:href='#g3-101'/>
+<use x='121.142' y='226.079' xlink:href='#g3-100'/>
+<use x='125.515' y='226.079' xlink:href='#g3-105'/>
+<use x='127.535' y='226.079' xlink:href='#g3-115'/>
+</g>
+<g transform='matrix(1 0 0 1 159.716 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-108'/>
+<use x='116.507' y='226.079' xlink:href='#g3-97'/>
+<use x='120.34' y='226.079' xlink:href='#g3-114'/>
+<use x='123.232' y='226.079' xlink:href='#g3-115'/>
+<use x='126.478' y='226.079' xlink:href='#g3-111'/>
+<use x='130.712' y='226.079' xlink:href='#g3-110'/>
+<use x='135.085' y='226.079' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 215.596 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-109'/>
+<use x='121.211' y='226.079' xlink:href='#g3-115'/>
+<use x='124.458' y='226.079' xlink:href='#g3-116'/>
+<use x='127.516' y='226.079' xlink:href='#g3-114'/>
+<use x='130.408' y='226.079' xlink:href='#g3-101'/>
+<use x='134.171' y='226.079' xlink:href='#g3-115'/>
+<use x='137.418' y='226.079' xlink:href='#g3-115'/>
+<use x='140.664' y='226.079' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 277.158 34.954)'>
+<use x='114.487' y='226.079' xlink:href='#g3-114'/>
+<use x='117.379' y='226.079' xlink:href='#g3-112'/>
+<use x='121.751' y='226.079' xlink:href='#g3-116'/>
+<use x='124.809' y='226.079' xlink:href='#g3-101'/>
+<use x='128.573' y='226.079' xlink:href='#g3-115'/>
+<use x='131.819' y='226.079' xlink:href='#g3-116'/>
+<use x='134.877' y='226.079' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 22.192)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -11.361)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -44.915)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -78.468)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -112.021)'>
+<use x='114.487' y='226.079' xlink:href='#g2-50'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -145.574)'>
+<use x='114.487' y='226.079' xlink:href='#g2-50'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-120'/>
+</g>
+<path d='M82.148 179.531H434.164' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M86.328 246.637H89.566V179.531H86.328ZM144.996 246.637H148.234V179.531H144.996ZM203.668 246.637H206.902V179.531H203.668ZM262.336 246.637H265.574V179.531H262.336ZM321.004 246.637H324.242V179.531H321.004ZM379.672 246.637H382.91V179.531H379.672Z' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M86.328 246.637H89.566V179.531H86.328ZM144.996 246.637H148.234V179.531H144.996ZM203.668 246.637H206.902V179.531H203.668ZM262.336 246.637H265.574V179.531H262.336ZM321.004 246.637H324.242V179.531H321.004ZM379.672 246.637H382.91V179.531H379.672Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M87.949 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M85.953 179.531H89.938' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M87.949 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M85.953 179.531H89.938' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M146.617 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M144.625 179.531H148.609' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M146.617 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M144.625 179.531H148.609' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M205.285 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M203.293 179.531H207.277' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M205.285 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M203.293 179.531H207.277' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M263.953 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M261.961 179.531H265.945' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M263.953 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M261.961 179.531H265.945' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M322.625 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M320.629 179.531H324.617' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M322.625 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M320.629 179.531H324.617' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M381.293 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M379.301 179.531H383.285' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M381.293 179.531' fill='#fff' clip-path='url(#clip1)'/>
+<path d='M379.301 179.531H383.285' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M91.559 246.637H94.797V180.336H91.559ZM150.227 246.637H153.465V177.449H150.227ZM208.899 246.637H212.133V179.598H208.899ZM267.567 246.637H270.805V186.441H267.567ZM326.234 246.637H329.473V78.871H326.234ZM384.902 246.637H388.141V162.754H384.902Z' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M91.559 246.637H94.797V180.336H91.559ZM150.227 246.637H153.465V177.449H150.227ZM208.899 246.637H212.133V179.598H208.899ZM267.567 246.637H270.805V186.441H267.567ZM326.234 246.637H329.473V78.871H326.234ZM384.902 246.637H388.141V162.754H384.902Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M93.18 180.336' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M91.184 180.336H95.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M93.18 180.336' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M91.184 180.336H95.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M151.848 177.449' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M149.855 177.45H153.84' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M151.848 177.449' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M149.855 177.45H153.84' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M210.516 179.598' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M208.523 179.598H212.507' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M210.516 179.598' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M208.523 179.598H212.507' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.184 186.441' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M267.191 186.442H271.175' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.184 186.441' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M267.191 186.442H271.175' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M327.856 78.871' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M325.859 78.871H329.847' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M327.856 78.871' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M325.859 78.871H329.847' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M386.524 162.754' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M384.531 162.753H388.515' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M386.524 162.754' fill='#f0e0f0' clip-path='url(#clip1)'/>
+<path d='M384.531 162.753H388.515' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M96.789 246.637H100.027V87.73H96.789ZM155.457 246.637H158.695V189.262H155.457ZM214.129 246.637H217.363V161.074H214.129ZM272.797 246.637H276.035V221.738H272.797ZM331.465 246.637H334.703V194.965H331.465ZM390.133 246.637H393.371V212.949H390.133Z' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M96.789 246.637H100.027V87.73H96.789ZM155.457 246.637H158.695V189.262H155.457ZM214.129 246.637H217.363V161.074H214.129ZM272.797 246.637H276.035V221.738H272.797ZM331.465 246.637H334.703V194.965H331.465ZM390.133 246.637H393.371V212.949H390.133Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M98.41 87.73' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M96.414 87.73H100.399' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M98.41 87.73' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M96.414 87.73H100.399' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M157.078 189.262' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M155.086 189.261H159.071' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M157.078 189.262' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M155.086 189.261H159.071' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M215.746 161.074' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M213.754 161.074H217.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M215.746 161.074' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M213.754 161.074H217.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.414 221.738' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M272.422 221.739H276.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.414 221.738' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M272.422 221.739H276.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M333.086 194.965' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M331.09 194.964H335.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M333.086 194.965' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M331.09 194.964H335.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M391.754 212.949' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M389.762 212.949H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M391.754 212.949' fill='#e1c2e1' clip-path='url(#clip1)'/>
+<path d='M389.762 212.949H393.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M102.02 246.637H105.258V152.219H102.02ZM160.688 246.637H163.926V180.535H160.688ZM219.359 246.637H222.594V174.766H219.359ZM278.027 246.637H281.266V206.172H278.027ZM336.695 246.637H339.934V192.953H336.695ZM395.363 246.637H398.602V183.223H395.363Z' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M102.02 246.637H105.258V152.219H102.02ZM160.688 246.637H163.926V180.535H160.688ZM219.359 246.637H222.594V174.766H219.359ZM278.027 246.637H281.266V206.172H278.027ZM336.695 246.637H339.934V192.953H336.695ZM395.363 246.637H398.602V183.223H395.363Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M103.641 152.219' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M101.644 152.219H105.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M103.641 152.219' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M101.644 152.219H105.629' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M162.309 180.535' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M160.316 180.536H164.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M162.309 180.535' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M160.316 180.536H164.301' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M220.977 174.766' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M218.984 174.765H222.969' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M220.977 174.766' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M218.984 174.765H222.969' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.645 206.172' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M277.652 206.172H281.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.645 206.172' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M277.652 206.172H281.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M338.317 192.953' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M336.32 192.953H340.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M338.317 192.953' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M336.32 192.953H340.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M396.984 183.223' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M394.992 183.223H398.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M396.984 183.223' fill='#d1a3d1' clip-path='url(#clip1)'/>
+<path d='M394.992 183.223H398.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M107.25 246.637H110.488V154.5H107.25ZM165.918 246.637H169.156V169.734H165.918ZM224.59 246.637H227.824V134.703H224.59ZM283.258 246.637H286.496V192.281H283.258ZM341.926 246.637H345.164V197.313H341.926ZM400.594 246.637H403.832V195.703H400.594Z' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M107.25 246.637H110.488V154.5H107.25ZM165.918 246.637H169.156V169.734H165.918ZM224.59 246.637H227.824V134.703H224.59ZM283.258 246.637H286.496V192.281H283.258ZM341.926 246.637H345.164V197.313H341.926ZM400.594 246.637H403.832V195.703H400.594Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.871 154.5' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M106.875 154.5H110.86' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.871 154.5' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M106.875 154.5H110.86' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M167.539 169.734' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M165.547 169.734H169.532' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M167.539 169.734' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M165.547 169.734H169.532' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M226.207 134.703' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M224.215 134.703H228.2' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M226.207 134.703' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M224.215 134.703H228.2' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.875 192.281' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M282.883 192.281H286.868' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.875 192.281' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M282.883 192.281H286.868' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M343.547 197.313' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M341.551 197.312H345.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M343.547 197.313' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M341.551 197.312H345.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M402.215 195.703' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M400.223 195.704H404.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M402.215 195.703' fill='#c285c2' clip-path='url(#clip1)'/>
+<path d='M400.223 195.704H404.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M112.481 246.637H115.719V167.922H112.481ZM171.149 246.637H174.387V172.148H171.149ZM229.82 246.637H233.055V160.07H229.82ZM288.488 246.637H291.727V196.305H288.488ZM347.156 246.637H350.395V78.871H347.156ZM405.824 246.637H409.063V146.379H405.824Z' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M112.481 246.637H115.719V167.922H112.481ZM171.149 246.637H174.387V172.148H171.149ZM229.82 246.637H233.055V160.07H229.82ZM288.488 246.637H291.727V196.305H288.488ZM347.156 246.637H350.395V78.871H347.156ZM405.824 246.637H409.063V146.379H405.824Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M114.098 167.922' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M112.105 167.922H116.09' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M114.098 167.922' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M112.105 167.922H116.09' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M172.77 172.148' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M170.777 172.148H174.762' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M172.77 172.148' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M170.777 172.148H174.762' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M231.438 160.07' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M229.445 160.07H233.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M231.438 160.07' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M229.445 160.07H233.43' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.106 196.305' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M288.113 196.304H292.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.106 196.305' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M288.113 196.304H292.098' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M348.777 78.871' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M346.781 78.871H350.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M348.777 78.871' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M346.781 78.871H350.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M407.445 146.379' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M405.453 146.379H409.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M407.445 146.379' fill='#b366b3' clip-path='url(#clip1)'/>
+<path d='M405.453 146.379H409.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M117.711 246.637H120.949V153.223H117.711ZM176.379 246.637H179.617V169.465H176.379ZM235.051 246.637H238.285V174.633H235.051ZM293.719 246.637H296.957V215.766H293.719ZM352.387 246.637H355.625V78.871H352.387ZM411.055 246.637H414.293V191.742H411.055Z' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M117.711 246.637H120.949V153.223H117.711ZM176.379 246.637H179.617V169.465H176.379ZM235.051 246.637H238.285V174.633H235.051ZM293.719 246.637H296.957V215.766H293.719ZM352.387 246.637H355.625V78.871H352.387ZM411.055 246.637H414.293V191.742H411.055Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M119.328 153.223' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M117.336 153.222H121.321' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M119.328 153.223' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M117.336 153.222H121.321' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M178 169.465' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M176.008 169.465H179.993' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M178 169.465' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M176.008 169.465H179.993' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M236.668 174.633' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M234.676 174.633H238.661' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M236.668 174.633' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M234.676 174.633H238.661' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.336 215.766' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M293.344 215.765H297.329' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.336 215.766' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M293.344 215.765H297.329' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M354.008 78.871' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M352.012 78.871H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M354.008 78.871' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M352.012 78.871H356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M412.676 191.742' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M410.684 191.742H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M412.676 191.742' fill='#a447a4' clip-path='url(#clip1)'/>
+<path d='M410.684 191.742H414.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M122.941 246.637H126.18V177.047H122.941ZM181.609 246.637H184.848V178.457H181.609ZM240.281 246.637H243.516V178.992H240.281ZM298.949 246.637H302.188V221.875H298.949ZM357.617 246.637H360.856V78.871H357.617ZM416.285 246.637H419.524V157.25H416.285Z' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M122.941 246.637H126.18V177.047H122.941ZM181.609 246.637H184.848V178.457H181.609ZM240.281 246.637H243.516V178.992H240.281ZM298.949 246.637H302.188V221.875H298.949ZM357.617 246.637H360.856V78.871H357.617ZM416.285 246.637H419.524V157.25H416.285Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M124.559 177.047' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M122.566 177.047H126.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M124.559 177.047' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M122.566 177.047H126.551' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M183.231 178.457' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M181.238 178.457H185.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M183.231 178.457' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M181.238 178.457H185.223' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M241.899 178.992' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M239.906 178.992H243.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M241.899 178.992' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M239.906 178.992H243.891' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M300.567 221.875' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M298.574 221.875H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M300.567 221.875' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M298.574 221.875H302.559' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M359.238 78.871' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M357.242 78.871H361.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M359.238 78.871' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M357.242 78.871H361.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M417.906 157.25' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M415.914 157.25H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M417.906 157.25' fill='#942994' clip-path='url(#clip1)'/>
+<path d='M415.914 157.25H419.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M128.172 246.637H131.41V182.414H128.172ZM186.84 246.637H190.078V170.805H186.84ZM245.512 246.637H248.746V179.059H245.512ZM304.18 246.637H307.418V207.176H304.18ZM362.848 246.637H366.086V153.629H362.848ZM421.516 246.637H424.754V207.313H421.516Z' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M128.172 246.637H131.41V182.414H128.172ZM186.84 246.637H190.078V170.805H186.84ZM245.512 246.637H248.746V179.059H245.512ZM304.18 246.637H307.418V207.176H304.18ZM362.848 246.637H366.086V153.629H362.848ZM421.516 246.637H424.754V207.313H421.516Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M129.789 182.414' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M127.797 182.415H131.782' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M129.789 182.414' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M127.797 182.415H131.782' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M188.461 170.805' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M186.469 170.805H190.454' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M188.461 170.805' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M186.469 170.805H190.454' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M247.129 179.059' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M245.137 179.058H249.122' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M247.129 179.059' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M245.137 179.058H249.122' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M305.797 207.176' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M303.804 207.176H307.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M305.797 207.176' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M303.804 207.176H307.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M364.469 153.629' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M362.473 153.629H366.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M364.469 153.629' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M362.473 153.629H366.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M423.137 207.313' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M421.144 207.313H425.128' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M423.137 207.313' fill='#850a85' clip-path='url(#clip1)'/>
+<path d='M421.144 207.313H425.128' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M133.402 246.637H136.641V178.055H133.402ZM192.07 246.637H195.309V164.969H192.07ZM250.742 246.637H253.977V175.703H250.742ZM309.41 246.637H312.649V184.027H309.41ZM368.078 246.637H371.317V99.809H368.078ZM426.746 246.637H429.984V143.023H426.746Z' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M133.402 246.637H136.641V178.055H133.402ZM192.07 246.637H195.309V164.969H192.07ZM250.742 246.637H253.977V175.703H250.742ZM309.41 246.637H312.649V184.027H309.41ZM368.078 246.637H371.317V99.809H368.078ZM426.746 246.637H429.984V143.023H426.746Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M135.02 178.055' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M133.027 178.055H137.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M135.02 178.055' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M133.027 178.055H137.012' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M193.692 164.969' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M191.699 164.969H195.684' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M193.692 164.969' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M191.699 164.969H195.684' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M252.359 175.703' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M250.367 175.703H254.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M252.359 175.703' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M250.367 175.703H254.352' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M311.027 184.027' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M309.035 184.027H313.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M311.027 184.027' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M309.035 184.027H313.02' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M369.699 99.809' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M367.703 99.809H371.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M369.699 99.809' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M367.703 99.809H371.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M428.367 143.023' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M426.375 143.023H430.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M428.367 143.023' fill='#760076' clip-path='url(#clip1)'/>
+<path d='M426.375 143.023H430.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<g transform='matrix(0 -1 1 0 -136.497 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -77.828 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.159 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 39.51 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 98.179 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 156.848 287.813)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -131.267 288.618)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -72.598 285.733)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -13.929 287.88)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 44.74 294.725)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 103.409 187.154)'>
+<use x='109.598' y='226.079' xlink:href='#g4-1'/>
+<use x='113.103' y='226.079' xlink:href='#g4-1'/>
+<use x='116.608' y='226.079' xlink:href='#g4-1'/>
+<use x='120.114' y='226.079' xlink:href='#g2-51'/>
+<use x='122.76' y='226.079' xlink:href='#g2-46'/>
+<use x='124.23' y='226.079' xlink:href='#g2-49'/>
+<use x='126.877' y='226.079' xlink:href='#g2-55'/>
+<use x='129.523' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 162.078 271.036)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-50'/>
+<use x='121.25' y='226.079' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -126.036 196.012)'>
+<use x='114.487' y='226.079' xlink:href='#g2-50'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -67.367 297.543)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-56'/>
+<use x='121.25' y='226.079' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -8.698 269.359)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-50'/>
+<use x='121.25' y='226.079' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 49.971 330.023)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 108.64 303.247)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-55'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 167.309 321.232)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -120.806 260.501)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-52'/>
+<use x='121.25' y='226.079' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 -62.137 288.819)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -3.468 283.048)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 55.201 314.454)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-54'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 113.87 301.234)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-56'/>
+<use x='121.25' y='226.079' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 172.539 291.504)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 -115.575 262.782)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -56.906 278.015)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 1.763 242.986)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-54'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 60.432 300.563)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-56'/>
+<use x='121.25' y='226.079' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 119.101 305.596)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-55'/>
+<use x='121.25' y='226.079' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 177.77 303.985)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-55'/>
+<use x='121.25' y='226.079' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -110.345 276.204)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 -51.676 280.431)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 6.993 268.352)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-50'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 65.662 304.589)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-55'/>
+<use x='121.25' y='226.079' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 124.331 187.154)'>
+<use x='109.598' y='226.079' xlink:href='#g4-1'/>
+<use x='113.103' y='226.079' xlink:href='#g4-1'/>
+<use x='116.608' y='226.079' xlink:href='#g4-1'/>
+<use x='120.114' y='226.079' xlink:href='#g2-53'/>
+<use x='122.76' y='226.079' xlink:href='#g2-46'/>
+<use x='124.23' y='226.079' xlink:href='#g2-51'/>
+<use x='126.877' y='226.079' xlink:href='#g2-50'/>
+<use x='129.523' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 183 254.663)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-52'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -105.114 261.507)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -46.445 277.747)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 12.224 282.914)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 70.893 324.05)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-52'/>
+<use x='121.25' y='226.079' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 129.562 187.154)'>
+<use x='109.598' y='226.079' xlink:href='#g4-1'/>
+<use x='113.103' y='226.079' xlink:href='#g4-1'/>
+<use x='116.608' y='226.079' xlink:href='#g4-1'/>
+<use x='120.114' y='226.079' xlink:href='#g2-50'/>
+<use x='122.76' y='226.079' xlink:href='#g2-46'/>
+<use x='124.23' y='226.079' xlink:href='#g2-56'/>
+<use x='126.877' y='226.079' xlink:href='#g2-53'/>
+<use x='129.523' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 188.231 300.026)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-56'/>
+<use x='121.25' y='226.079' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -99.884 285.33)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 -41.215 286.739)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 17.454 287.276)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 76.123 330.157)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 134.792 187.154)'>
+<use x='109.598' y='226.079' xlink:href='#g4-1'/>
+<use x='113.103' y='226.079' xlink:href='#g4-1'/>
+<use x='116.608' y='226.079' xlink:href='#g4-1'/>
+<use x='120.114' y='226.079' xlink:href='#g2-52'/>
+<use x='122.76' y='226.079' xlink:href='#g2-46'/>
+<use x='124.23' y='226.079' xlink:href='#g2-50'/>
+<use x='126.877' y='226.079' xlink:href='#g2-51'/>
+<use x='129.523' y='226.079' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 193.461 265.534)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -94.654 290.698)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.985 279.089)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 22.684 287.343)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 81.353 315.461)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 140.022 261.91)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-51'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 198.691 315.595)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -89.423 286.337)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.754 273.251)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-50'/>
+<use x='121.25' y='226.079' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 27.915 283.988)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-48'/>
+<use x='121.25' y='226.079' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 86.584 292.309)'>
+<use x='114.487' y='226.079' xlink:href='#g2-48'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-57'/>
+<use x='121.25' y='226.079' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 145.253 208.091)'>
+<use x='114.487' y='226.079' xlink:href='#g2-50'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-49'/>
+<use x='121.25' y='226.079' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 203.922 251.307)'>
+<use x='114.487' y='226.079' xlink:href='#g2-49'/>
+<use x='117.133' y='226.079' xlink:href='#g2-46'/>
+<use x='118.603' y='226.079' xlink:href='#g2-53'/>
+<use x='121.25' y='226.079' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 -166.719 329.135)'>
+<use x='114.487' y='226.079' xlink:href='#g1-82'/>
+<use x='120.457' y='226.079' xlink:href='#g1-101'/>
+<use x='124.553' y='226.079' xlink:href='#g1-108'/>
+<use x='126.753' y='226.079' xlink:href='#g1-97'/>
+<use x='131.181' y='226.079' xlink:href='#g1-116'/>
+<use x='134.509' y='226.079' xlink:href='#g1-105'/>
+<use x='136.709' y='226.079' xlink:href='#g1-118'/>
+<use x='140.957' y='226.079' xlink:href='#g1-101'/>
+<use x='148.124' y='226.079' xlink:href='#g1-114'/>
+<use x='151.272' y='226.079' xlink:href='#g1-115'/>
+<use x='154.805' y='226.079' xlink:href='#g1-115'/>
+<use x='161.409' y='226.079' xlink:href='#g3-40'/>
+<use x='164.702' y='226.079' xlink:href='#g3-108'/>
+<use x='166.722' y='226.079' xlink:href='#g3-111'/>
+<use x='170.721' y='226.079' xlink:href='#g3-119'/>
+<use x='176.27' y='226.079' xlink:href='#g3-101'/>
+<use x='180.034' y='226.079' xlink:href='#g3-114'/>
+<use x='185.749' y='226.079' xlink:href='#g3-105'/>
+<use x='187.769' y='226.079' xlink:href='#g3-115'/>
+<use x='193.838' y='226.079' xlink:href='#g3-98'/>
+<use x='198.446' y='226.079' xlink:href='#g3-101'/>
+<use x='202.209' y='226.079' xlink:href='#g3-116'/>
+<use x='205.267' y='226.079' xlink:href='#g3-116'/>
+<use x='208.325' y='226.079' xlink:href='#g3-101'/>
+<use x='212.089' y='226.079' xlink:href='#g3-114'/>
+<use x='214.981' y='226.079' xlink:href='#g3-41'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg b/extlib/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg
new file mode 100644 (file)
index 0000000..c81072e
--- /dev/null
@@ -0,0 +1,1131 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='381.627pt' height='254.34pt' viewBox='106.732 54.992 381.627 254.34'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip2'>
+<path d='M135.949 246.637H487.961V78.871H135.949Z'/>
+</clipPath>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-114' d='M1.462-1.91C1.462-2.851 2.197-3.425 3.013-3.434V-4.08C2.367-4.071 1.775-3.748 1.408-3.219V-4.035H.744V0H1.462V-1.91Z'/>
+<path id='g1-115' d='M3.165-3.847C2.609-4.098 2.197-4.133 1.829-4.133C1.623-4.133 .305-4.133 .305-2.95C.305-2.52 .565-2.251 .664-2.152C1.004-1.856 1.237-1.811 1.847-1.695C2.134-1.641 2.645-1.542 2.645-1.085C2.645-.502 1.919-.502 1.802-.502C1.273-.502 .762-.681 .377-.95L.26-.296C.798-.009 1.345 .099 1.802 .099C2.385 .099 3.318-.09 3.318-1.157C3.318-1.47 3.192-1.784 2.878-2.053C2.573-2.313 2.304-2.367 1.748-2.475C1.426-2.537 .977-2.618 .977-3.04C.977-3.569 1.614-3.569 1.748-3.569C2.403-3.569 2.789-3.362 3.049-3.219L3.165-3.847Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-45' xlink:href='#g0-45' transform='scale(1.143)'/>
+<use id='g3-49' xlink:href='#g0-49' transform='scale(1.143)'/>
+<use id='g3-54' xlink:href='#g0-54' transform='scale(1.143)'/>
+<use id='g3-56' xlink:href='#g0-56' transform='scale(1.143)'/>
+<use id='g3-58' xlink:href='#g0-58' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-103' xlink:href='#g0-103' transform='scale(1.143)'/>
+<use id='g3-104' xlink:href='#g0-104' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-106' xlink:href='#g0-106' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-112' xlink:href='#g0-112' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g3-120' xlink:href='#g0-120' transform='scale(1.143)'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-44' d='M1.339-.007V-.628H.711V0H.907L.704 .893H1.018L1.339-.007Z'/>
+<path id='g0-45' d='M2.05-1.332V-1.771H.084V-1.332H2.05Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-58' d='M1.339-3.096H.711V-2.469H1.339V-3.096ZM.711-.628V0H1.339V-.628H.711Z'/>
+<path id='g0-64' d='M4.142-.614C4.038-.614 4.024-.614 3.968-.586C3.626-.467 3.271-.391 2.901-.391C1.778-.391 .976-1.339 .976-2.42C.976-3.592 1.883-4.449 2.859-4.449C3.055-4.449 3.515-4.4 3.745-3.843C3.55-3.954 3.333-4.003 3.152-4.003C2.406-4.003 1.778-3.306 1.778-2.42C1.778-1.513 2.427-.837 3.145-.837C3.689-.837 4.519-1.276 4.519-2.518C4.519-3.222 4.47-4.91 2.866-4.91C1.541-4.91 .411-3.815 .411-2.42C.411-1.039 1.527 .07 2.873 .07C3.515 .07 4.115-.195 4.519-.614H4.142ZM3.152-1.297C2.72-1.297 2.343-1.778 2.343-2.42C2.343-3.082 2.734-3.543 3.145-3.543C3.578-3.543 3.954-3.062 3.954-2.42C3.954-1.757 3.564-1.297 3.152-1.297Z'/>
+<path id='g0-67' d='M4.317-.851C3.829-.551 3.605-.418 2.908-.418C1.827-.418 1.172-1.43 1.172-2.434C1.172-3.466 1.89-4.435 2.908-4.435C3.368-4.435 3.843-4.289 4.163-4.045L4.275-4.679C3.787-4.861 3.396-4.917 2.887-4.917C1.506-4.917 .474-3.773 .474-2.427C.474-.99 1.569 .07 2.929 .07C3.612 .07 3.898-.07 4.359-.321L4.317-.851Z'/>
+<path id='g0-71' d='M4.442-2.085H2.88V-1.625H3.829V-.558C3.522-.481 3.222-.418 2.908-.418C1.834-.418 1.172-1.43 1.172-2.427C1.172-3.382 1.82-4.435 2.873-4.435C3.515-4.435 3.919-4.24 4.268-3.947L4.38-4.582C3.898-4.812 3.473-4.924 2.943-4.924C1.534-4.924 .474-3.822 .474-2.427C.474-1.067 1.527 .07 2.901 .07C3.403 .07 3.996-.042 4.442-.272V-2.085Z'/>
+<path id='g0-73' d='M1.381-4.84H.676V0H1.381V-4.84Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-85' d='M4.4-4.84H3.794V-1.625C3.794-.69 3.166-.265 2.566-.265S1.381-.697 1.381-1.618V-4.84H.676V-1.632C.676-.607 1.555 .146 2.559 .146C3.557 .146 4.4-.614 4.4-1.632V-4.84Z'/>
+<path id='g0-88' d='M2.755-2.552L4.519-4.84H3.759L2.413-3.055L1.039-4.84H.209L2.071-2.552L.105 0H.865L2.413-2.099L3.996 0H4.826L2.755-2.552Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-103' d='M3.508-3.166C3.354-3.166 2.887-3.159 2.357-2.957L2.343-2.95C2.092-3.117 1.848-3.166 1.646-3.166C.962-3.166 .453-2.629 .453-2.029C.453-1.785 .537-1.534 .697-1.339C.6-1.22 .495-1.025 .495-.76C.495-.488 .607-.314 .669-.23C.286-.007 .209 .314 .209 .481C.209 1.011 .941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 .481C3.487-.502 2.267-.502 1.967-.502H1.318C1.206-.502 .907-.502 .907-.865C.907-1.004 .955-1.074 .962-1.088C1.206-.934 1.451-.886 1.639-.886C2.322-.886 2.831-1.423 2.831-2.022C2.831-2.246 2.769-2.448 2.643-2.636C2.615-2.678 2.615-2.685 2.615-2.692C2.615-2.72 3.034-2.72 3.068-2.72C3.075-2.72 3.34-2.72 3.592-2.692L3.508-3.166ZM1.646-1.318C1.269-1.318 .99-1.555 .99-2.022C.99-2.566 1.339-2.734 1.639-2.734C2.015-2.734 2.294-2.497 2.294-2.029C2.294-1.485 1.946-1.318 1.646-1.318ZM1.974 .042C2.134 .042 2.957 .042 2.957 .488C2.957 .788 2.434 .997 1.848 .997S.739 .788 .739 .488C.739 .453 .739 .042 1.304 .042H1.974Z'/>
+<path id='g0-104' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.625-3.166 1.304-2.817 1.165-2.671V-4.84H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-106' d='M1.381-4.784H.676V-4.08H1.381V-4.784ZM-.453 1.186C-.133 1.36 .181 1.423 .446 1.423C.928 1.423 1.381 1.053 1.381 .411V-3.096H.795V.46C.795 .586 .795 .697 .649 .816C.488 .934 .293 .934 .23 .934C-.063 .934-.244 .802-.328 .725L-.453 1.186Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-117' d='M3.243-3.096H2.636V-1.074C2.636-.516 2.162-.342 1.757-.342C1.241-.342 1.186-.481 1.186-.802V-3.096H.579V-.76C.579-.139 .851 .07 1.339 .07C1.625 .07 2.239 .014 2.657-.321V0H3.243V-3.096Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+<path id='g0-122' d='M2.957-2.803V-3.096H.307V-2.65H1.332C1.416-2.65 1.499-2.657 1.583-2.657H2.127L.209-.307V0H2.978V-.467H1.897C1.813-.467 1.73-.46 1.646-.46H1.039L2.957-2.803Z'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g4-2' d='M4.13-2.481C4.184-2.535 4.204-2.57 4.204-2.615C4.204-2.69 4.139-2.755 4.065-2.755C4.01-2.755 3.985-2.73 3.93-2.675L2.7-1.445L1.465-2.68C1.41-2.735 1.375-2.755 1.33-2.755C1.255-2.755 1.191-2.69 1.191-2.615C1.191-2.56 1.215-2.535 1.27-2.481L2.501-1.245L1.27-.01C1.215 .045 1.191 .07 1.191 .125C1.191 .199 1.255 .264 1.33 .264C1.385 .264 1.41 .239 1.46 .189L2.695-1.046L3.97 .229C3.995 .249 4.03 .264 4.065 .264C4.139 .264 4.204 .199 4.204 .125C4.204 .095 4.194 .075 4.184 .05C4.164 .02 3.238-.892 2.894-1.245L4.13-2.481Z'/>
+<use id='g2-41' xlink:href='#g0-41' transform='scale(.714)'/>
+<use id='g2-44' xlink:href='#g0-44' transform='scale(.714)'/>
+<use id='g2-45' xlink:href='#g0-45' transform='scale(.714)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-64' xlink:href='#g0-64' transform='scale(.714)'/>
+<use id='g2-67' xlink:href='#g0-67' transform='scale(.714)'/>
+<use id='g2-71' xlink:href='#g0-71' transform='scale(.714)'/>
+<use id='g2-73' xlink:href='#g0-73' transform='scale(.714)'/>
+<use id='g2-85' xlink:href='#g0-85' transform='scale(.714)'/>
+<use id='g2-88' xlink:href='#g0-88' transform='scale(.714)'/>
+<use id='g2-97' xlink:href='#g0-97' transform='scale(.714)'/>
+<use id='g2-98' xlink:href='#g0-98' transform='scale(.714)'/>
+<use id='g2-99' xlink:href='#g0-99' transform='scale(.714)'/>
+<use id='g2-100' xlink:href='#g0-100' transform='scale(.714)'/>
+<use id='g2-101' xlink:href='#g0-101' transform='scale(.714)'/>
+<use id='g2-103' xlink:href='#g0-103' transform='scale(.714)'/>
+<use id='g2-104' xlink:href='#g0-104' transform='scale(.714)'/>
+<use id='g2-105' xlink:href='#g0-105' transform='scale(.714)'/>
+<use id='g2-108' xlink:href='#g0-108' transform='scale(.714)'/>
+<use id='g2-109' xlink:href='#g0-109' transform='scale(.714)'/>
+<use id='g2-110' xlink:href='#g0-110' transform='scale(.714)'/>
+<use id='g2-111' xlink:href='#g0-111' transform='scale(.714)'/>
+<use id='g2-114' xlink:href='#g0-114' transform='scale(.714)'/>
+<use id='g2-115' xlink:href='#g0-115' transform='scale(.714)'/>
+<use id='g2-116' xlink:href='#g0-116' transform='scale(.714)'/>
+<use id='g2-117' xlink:href='#g0-117' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<use id='g2-122' xlink:href='#g0-122' transform='scale(.714)'/>
+</defs>
+<g id='page2'>
+<path d='M194.617 255.492V246.637M253.285 255.492V246.637M311.953 255.492V246.637M370.625 255.492V246.637M429.293 255.492V246.637M194.617 70.016V78.871M253.285 70.016V78.871M311.953 70.016V78.871M370.625 70.016V78.871M429.293 70.016V78.871' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M165.281 250.887V246.637M223.953 250.887V246.637M282.621 250.887V246.637M341.289 250.887V246.637M399.957 250.887V246.637M458.629 250.887V246.637M165.281 74.617V78.871M223.953 74.617V78.871M282.621 74.617V78.871M341.289 74.617V78.871M399.957 74.617V78.871M458.629 74.617V78.871' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 246.637H140.199M135.949 213.082H140.199M135.949 179.531H140.199M135.949 145.976H140.199M135.949 112.426H140.199M135.949 78.871H140.199M487.961 246.637H483.711M487.961 213.082H483.711M487.961 179.531H483.711M487.961 145.976H483.711M487.961 112.426H483.711M487.961 78.871H483.711' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M135.949 246.637V78.871H487.961V246.637H135.949Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -21.265 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-97'/>
+<use x='172.353' y='186.041' xlink:href='#g3-108'/>
+<use x='174.373' y='186.041' xlink:href='#g3-108'/>
+<use x='176.393' y='186.041' xlink:href='#g3-111'/>
+<use x='180.863' y='186.041' xlink:href='#g3-99'/>
+<use x='184.627' y='186.041' xlink:href='#g3-45'/>
+<use x='187.449' y='186.041' xlink:href='#g3-116'/>
+<use x='190.507' y='186.041' xlink:href='#g3-101'/>
+<use x='194.271' y='186.041' xlink:href='#g3-115'/>
+<use x='197.517' y='186.041' xlink:href='#g3-116'/>
+<use x='200.575' y='186.041' xlink:href='#g3-49'/>
+</g>
+<g transform='matrix(1 0 0 1 36.532 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-97'/>
+<use x='172.353' y='186.041' xlink:href='#g3-108'/>
+<use x='174.373' y='186.041' xlink:href='#g3-108'/>
+<use x='176.393' y='186.041' xlink:href='#g3-111'/>
+<use x='180.863' y='186.041' xlink:href='#g3-99'/>
+<use x='184.627' y='186.041' xlink:href='#g3-45'/>
+<use x='187.449' y='186.041' xlink:href='#g3-116'/>
+<use x='190.507' y='186.041' xlink:href='#g3-101'/>
+<use x='194.271' y='186.041' xlink:href='#g3-115'/>
+<use x='197.517' y='186.041' xlink:href='#g3-116'/>
+<use x='200.575' y='186.041' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 94.98 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-115'/>
+<use x='171.531' y='186.041' xlink:href='#g3-104'/>
+<use x='175.904' y='186.041' xlink:href='#g3-54'/>
+<use x='180.138' y='186.041' xlink:href='#g3-98'/>
+<use x='184.746' y='186.041' xlink:href='#g3-101'/>
+<use x='188.509' y='186.041' xlink:href='#g3-110'/>
+<use x='192.882' y='186.041' xlink:href='#g3-99'/>
+<use x='196.646' y='186.041' xlink:href='#g3-104'/>
+<use x='201.018' y='186.041' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 153.649 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-115'/>
+<use x='171.531' y='186.041' xlink:href='#g3-104'/>
+<use x='175.904' y='186.041' xlink:href='#g3-56'/>
+<use x='180.138' y='186.041' xlink:href='#g3-98'/>
+<use x='184.746' y='186.041' xlink:href='#g3-101'/>
+<use x='188.509' y='186.041' xlink:href='#g3-110'/>
+<use x='192.882' y='186.041' xlink:href='#g3-99'/>
+<use x='196.646' y='186.041' xlink:href='#g3-104'/>
+<use x='201.018' y='186.041' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 207.225 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-120'/>
+<use x='172.187' y='186.041' xlink:href='#g3-109'/>
+<use x='178.912' y='186.041' xlink:href='#g3-97'/>
+<use x='182.98' y='186.041' xlink:href='#g3-108'/>
+<use x='185' y='186.041' xlink:href='#g3-108'/>
+<use x='187.02' y='186.041' xlink:href='#g3-111'/>
+<use x='191.49' y='186.041' xlink:href='#g3-99'/>
+<use x='195.254' y='186.041' xlink:href='#g3-45'/>
+<use x='198.076' y='186.041' xlink:href='#g3-116'/>
+<use x='201.134' y='186.041' xlink:href='#g3-101'/>
+<use x='204.898' y='186.041' xlink:href='#g3-115'/>
+<use x='208.144' y='186.041' xlink:href='#g3-116'/>
+<use x='211.202' y='186.041' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 263.494 74.992)'>
+<use x='168.285' y='186.041' xlink:href='#g3-99'/>
+<use x='172.049' y='186.041' xlink:href='#g3-97'/>
+<use x='176.117' y='186.041' xlink:href='#g3-99'/>
+<use x='179.88' y='186.041' xlink:href='#g3-104'/>
+<use x='184.253' y='186.041' xlink:href='#g3-101'/>
+<use x='188.017' y='186.041' xlink:href='#g3-45'/>
+<use x='190.839' y='186.041' xlink:href='#g3-115'/>
+<use x='194.086' y='186.041' xlink:href='#g3-99'/>
+<use x='197.849' y='186.041' xlink:href='#g3-114'/>
+<use x='200.741' y='186.041' xlink:href='#g3-97'/>
+<use x='204.81' y='186.041' xlink:href='#g3-116'/>
+<use x='207.868' y='186.041' xlink:href='#g3-99'/>
+<use x='211.631' y='186.041' xlink:href='#g3-104'/>
+<use x='216.004' y='186.041' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 62.23)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.677)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -4.876)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -38.43)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -71.983)'>
+<use x='168.285' y='186.041' xlink:href='#g2-50'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -105.536)'>
+<use x='168.285' y='186.041' xlink:href='#g2-50'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-120'/>
+</g>
+<path d='M135.949 179.531H487.961' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M140.125 246.637H143.363V179.531H140.125ZM198.797 246.637H202.035V179.531H198.797ZM257.465 246.637H260.703V179.531H257.465ZM316.133 246.637H319.371V179.531H316.133ZM374.801 246.637H378.039V179.531H374.801ZM433.473 246.637H436.711V179.531H433.473Z' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M140.125 246.637H143.363V179.531H140.125ZM198.797 246.637H202.035V179.531H198.797ZM257.465 246.637H260.703V179.531H257.465ZM316.133 246.637H319.371V179.531H316.133ZM374.801 246.637H378.039V179.531H374.801ZM433.473 246.637H436.711V179.531H433.473Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M141.746 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M139.754 179.531H143.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M141.746 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M139.754 179.531H143.738' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M200.414 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M198.422 179.531H202.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M200.414 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M198.422 179.531H202.406' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M259.082 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M257.09 179.531H261.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M259.082 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M257.09 179.531H261.078' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M317.754 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M315.762 179.531H319.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M317.754 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M315.762 179.531H319.746' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M376.422 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M374.43 179.531H378.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M376.422 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M374.43 179.531H378.414' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M435.09 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M433.098 179.531H437.082' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M435.09 179.531' fill='#fff' clip-path='url(#clip2)'/>
+<path d='M433.098 179.531H437.082' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M145.356 246.637H148.594V180.066H145.356ZM204.028 246.637H207.266V179.195H204.028ZM262.695 246.637H265.934V181.008H262.695ZM321.363 246.637H324.602V179.934H321.363ZM380.031 246.637H383.27V175.637H380.031ZM438.703 246.637H441.942V179.664H438.703Z' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M145.356 246.637H148.594V180.066H145.356ZM204.028 246.637H207.266V179.195H204.028ZM262.695 246.637H265.934V181.008H262.695ZM321.363 246.637H324.602V179.934H321.363ZM380.031 246.637H383.27V175.637H380.031ZM438.703 246.637H441.942V179.664H438.703Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M146.977 180.066' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M144.984 180.067H148.968' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M146.977 180.066' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M144.984 180.067H148.968' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M205.645 179.195' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M203.652 179.196H207.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M205.645 179.195' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M203.652 179.196H207.636' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M264.313 181.008' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M262.32 181.007H266.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M264.313 181.008' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M262.32 181.007H266.308' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M322.984 179.934' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M320.992 179.934H324.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M322.984 179.934' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M320.992 179.934H324.976' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M381.652 175.637' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M379.66 175.637H383.644' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M381.652 175.637' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M379.66 175.637H383.644' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M440.32 179.664' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M438.328 179.664H442.312' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M440.32 179.664' fill='#f0e0f0' clip-path='url(#clip2)'/>
+<path d='M438.328 179.664H442.312' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M150.586 246.637H153.824V163.426H150.586ZM209.258 246.637H212.496V159.062H209.258ZM267.926 246.637H271.164V184.027H267.926ZM326.594 246.637H329.832V203.687H326.594ZM385.262 246.637H388.5V219.859H385.262ZM443.934 246.637H447.172V139.734H443.934Z' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M150.586 246.637H153.824V163.426H150.586ZM209.258 246.637H212.496V159.062H209.258ZM267.926 246.637H271.164V184.027H267.926ZM326.594 246.637H329.832V203.687H326.594ZM385.262 246.637H388.5V219.859H385.262ZM443.934 246.637H447.172V139.734H443.934Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M152.207 163.426' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M150.215 163.426H154.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M152.207 163.426' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M150.215 163.426H154.199' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M210.875 159.062' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M208.883 159.063H212.867' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M210.875 159.062' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M208.883 159.063H212.867' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M269.543 184.027' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M267.551 184.027H271.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M269.543 184.027' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M267.551 184.027H271.539' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M328.215 203.687' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M326.223 203.687H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M328.215 203.687' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M326.223 203.687H330.207' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M386.883 219.859' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M384.891 219.86H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M386.883 219.859' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M384.891 219.86H388.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M445.551 139.734' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M443.559 139.734H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M445.551 139.734' fill='#e1c2e1' clip-path='url(#clip2)'/>
+<path d='M443.559 139.734H447.543' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M155.817 246.637H159.055V183.824H155.817ZM214.488 246.637H217.727V176.109H214.488ZM273.156 246.637H276.395V181.344H273.156ZM331.824 246.637H335.063V193.086H331.824ZM390.492 246.637H393.731V195.164H390.492ZM449.164 246.637H452.402V144.566H449.164Z' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M155.817 246.637H159.055V183.824H155.817ZM214.488 246.637H217.727V176.109H214.488ZM273.156 246.637H276.395V181.344H273.156ZM331.824 246.637H335.063V193.086H331.824ZM390.492 246.637H393.731V195.164H390.492ZM449.164 246.637H452.402V144.566H449.164Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M157.438 183.824' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M155.445 183.824H159.429' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M157.438 183.824' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M155.445 183.824H159.429' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M216.106 176.109' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M214.113 176.11H218.097' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M216.106 176.109' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M214.113 176.11H218.097' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M274.774 181.344' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M272.781 181.344H276.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M274.774 181.344' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M272.781 181.344H276.769' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M333.445 193.086' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M331.453 193.085H335.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M333.445 193.086' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M331.453 193.085H335.437' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M392.113 195.164' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M390.121 195.164H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M392.113 195.164' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M390.121 195.164H394.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M450.781 144.566' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M448.789 144.567H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M450.781 144.566' fill='#d1a3d1' clip-path='url(#clip2)'/>
+<path d='M448.789 144.567H452.773' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M161.047 246.637H164.285V178.926H161.047ZM219.719 246.637H222.957V169.934H219.719ZM278.387 246.637H281.625V176.644H278.387ZM337.055 246.637H340.293V195.234H337.055ZM395.723 246.637H398.961V182.078H395.723ZM454.395 246.637H457.633V177.652H454.395Z' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M161.047 246.637H164.285V178.926H161.047ZM219.719 246.637H222.957V169.934H219.719ZM278.387 246.637H281.625V176.644H278.387ZM337.055 246.637H340.293V195.234H337.055ZM395.723 246.637H398.961V182.078H395.723ZM454.395 246.637H457.633V177.652H454.395Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M162.668 178.926' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M160.676 178.926H164.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M162.668 178.926' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M160.676 178.926H164.66' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M221.336 169.934' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M219.344 169.934H223.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M221.336 169.934' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M219.344 169.934H223.328' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M280.004 176.644' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M278.012 176.644H282' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M280.004 176.644' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M278.012 176.644H282' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M338.676 195.234' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M336.684 195.235H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M338.676 195.234' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M336.684 195.235H340.668' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M397.344 182.078' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M395.352 182.078H399.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M397.344 182.078' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M395.352 182.078H399.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M456.012 177.652' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M454.02 177.652H458.004' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M456.012 177.652' fill='#c285c2' clip-path='url(#clip2)'/>
+<path d='M454.02 177.652H458.004' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M166.278 246.637H169.516V179.598H166.278ZM224.949 246.637H228.188V144.098H224.949ZM283.617 246.637H286.856V172.82H283.617ZM342.285 246.637H345.524V155.91H342.285ZM400.953 246.637H404.192V172.484H400.953ZM459.625 246.637H462.863V172.016H459.625Z' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M166.278 246.637H169.516V179.598H166.278ZM224.949 246.637H228.188V144.098H224.949ZM283.617 246.637H286.856V172.82H283.617ZM342.285 246.637H345.524V155.91H342.285ZM400.953 246.637H404.192V172.484H400.953ZM459.625 246.637H462.863V172.016H459.625Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M167.899 179.598' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M165.906 179.598H169.89' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M167.899 179.598' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M165.906 179.598H169.89' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M226.567 144.098' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M224.574 144.098H228.558' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M226.567 144.098' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M224.574 144.098H228.558' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M285.234 172.82' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M283.242 172.82H287.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M285.234 172.82' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M283.242 172.82H287.23' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M343.906 155.91' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M341.914 155.91H345.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M343.906 155.91' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M341.914 155.91H345.898' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M402.574 172.484' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M400.582 172.484H404.566' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M402.574 172.484' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M400.582 172.484H404.566' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M461.242 172.016' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M459.25 172.015H463.234' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M461.242 172.016' fill='#b366b3' clip-path='url(#clip2)'/>
+<path d='M459.25 172.015H463.234' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M171.508 246.637H174.746V177.113H171.508ZM230.18 246.637H233.414V179.465H230.18ZM288.848 246.637H292.086V166.176H288.848ZM347.516 246.637H350.754V160.605H347.516ZM406.184 246.637H409.422V78.871H406.184ZM464.856 246.637H468.094V189.797H464.856Z' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M171.508 246.637H174.746V177.113H171.508ZM230.18 246.637H233.414V179.465H230.18ZM288.848 246.637H292.086V166.176H288.848ZM347.516 246.637H350.754V160.605H347.516ZM406.184 246.637H409.422V78.871H406.184ZM464.856 246.637H468.094V189.797H464.856Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M173.129 177.113' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M171.137 177.113H175.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M173.129 177.113' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M171.137 177.113H175.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M231.797 179.465' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M229.805 179.465H233.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M231.797 179.465' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M229.805 179.465H233.789' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M290.465 166.176' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M288.473 166.176H292.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M290.465 166.176' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M288.473 166.176H292.461' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M349.137 160.605' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M347.145 160.605H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M349.137 160.605' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M347.145 160.605H351.129' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M407.805 78.871' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M405.813 78.871H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M407.805 78.871' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M405.813 78.871H409.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M466.473 189.797' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M464.481 189.797H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M466.473 189.797' fill='#a447a4' clip-path='url(#clip2)'/>
+<path d='M464.481 189.797H468.465' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M176.738 246.637H179.977V167.383H176.738ZM235.41 246.637H238.645V78.871H235.41ZM294.078 246.637H297.317V143.09H294.078ZM352.746 246.637H355.984V166.711H352.746ZM411.414 246.637H414.652V219.391H411.414ZM470.086 246.637H473.324V160.336H470.086Z' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M176.738 246.637H179.977V167.383H176.738ZM235.41 246.637H238.645V78.871H235.41ZM294.078 246.637H297.317V143.09H294.078ZM352.746 246.637H355.984V166.711H352.746ZM411.414 246.637H414.652V219.391H411.414ZM470.086 246.637H473.324V160.336H470.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M178.36 167.383' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M176.367 167.383H180.351' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M178.36 167.383' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M176.367 167.383H180.351' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M237.027 78.871' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M235.035 78.871H239.019' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M237.027 78.871' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M235.035 78.871H239.019' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M295.695 143.09' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M293.703 143.089H297.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M295.695 143.09' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M293.703 143.089H297.691' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M354.367 166.711' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M352.375 166.711H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M354.367 166.711' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M352.375 166.711H356.359' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M413.035 219.391' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M411.043 219.391H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M413.035 219.391' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M411.043 219.391H415.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M471.703 160.336' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M469.711 160.336H473.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M471.703 160.336' fill='#942994' clip-path='url(#clip2)'/>
+<path d='M469.711 160.336H473.695' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M181.969 246.637H185.207V176.711H181.969ZM240.641 246.637H243.875V169.062H240.641ZM299.309 246.637H302.547V151.547H299.309ZM357.977 246.637H361.215V113.43H357.977ZM416.645 246.637H419.883V188.387H416.645ZM475.317 246.637H478.555V190.402H475.317Z' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M181.969 246.637H185.207V176.711H181.969ZM240.641 246.637H243.875V169.062H240.641ZM299.309 246.637H302.547V151.547H299.309ZM357.977 246.637H361.215V113.43H357.977ZM416.645 246.637H419.883V188.387H416.645ZM475.317 246.637H478.555V190.402H475.317Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M183.59 176.711' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M181.598 176.711H185.583' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M183.59 176.711' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M181.598 176.711H185.583' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M242.258 169.062' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M240.266 169.062H244.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M242.258 169.062' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M240.266 169.062H244.25' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M300.926 151.547' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M298.933 151.547H302.921' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M300.926 151.547' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M298.933 151.547H302.921' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M359.598 113.43' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M357.606 113.43H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M359.598 113.43' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M357.606 113.43H361.59' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M418.266 188.387' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M416.274 188.387H420.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M418.266 188.387' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M416.274 188.387H420.258' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M476.934 190.402' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M474.942 190.402H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M476.934 190.402' fill='#850a85' clip-path='url(#clip2)'/>
+<path d='M474.942 190.402H478.926' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M187.199 246.637H190.438V179.465H187.199ZM245.871 246.637H249.106V113.094H245.871ZM304.539 246.637H307.777V164.094H304.539ZM363.207 246.637H366.445V156.578H363.207ZM421.875 246.637H425.113V174.496H421.875ZM480.547 246.637H483.785V176.375H480.547Z' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M187.199 246.637H190.438V179.465H187.199ZM245.871 246.637H249.106V113.094H245.871ZM304.539 246.637H307.777V164.094H304.539ZM363.207 246.637H366.445V156.578H363.207ZM421.875 246.637H425.113V174.496H421.875ZM480.547 246.637H483.785V176.375H480.547Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M188.82 179.465' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M186.828 179.465H190.813' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M188.82 179.465' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M186.828 179.465H190.813' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M247.488 113.094' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M245.496 113.094H249.481' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M247.488 113.094' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M245.496 113.094H249.481' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M306.156 164.094' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M304.164 164.094H308.152' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M306.156 164.094' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M304.164 164.094H308.152' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M364.828 156.578' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M362.836 156.578H366.82' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M364.828 156.578' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M362.836 156.578H366.82' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M423.496 174.496' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M421.504 174.496H425.488' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M423.496 174.496' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M421.504 174.496H425.488' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M482.164 176.375' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M480.172 176.375H484.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M482.164 176.375' fill='#760076' clip-path='url(#clip2)'/>
+<path d='M480.172 176.375H484.156' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<path d='M369.781 308.934H487.762V273.68H369.781Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip2)'/>
+<g transform='matrix(1 0 0 1 204.818 118.327)'>
+<use x='168.285' y='162.131' xlink:href='#g2-99'/>
+<use x='170.637' y='162.131' xlink:href='#g2-53'/>
+<use x='173.284' y='162.131' xlink:href='#g2-45'/>
+<use x='175.048' y='162.131' xlink:href='#g2-49'/>
+<use x='177.694' y='162.131' xlink:href='#g2-56'/>
+<use x='180.341' y='162.131' xlink:href='#g2-120'/>
+<use x='182.779' y='162.131' xlink:href='#g2-108'/>
+<use x='184.042' y='162.131' xlink:href='#g2-97'/>
+<use x='186.438' y='162.131' xlink:href='#g2-114'/>
+<use x='188.245' y='162.131' xlink:href='#g2-103'/>
+<use x='190.891' y='162.131' xlink:href='#g2-101'/>
+<use x='193.244' y='162.131' xlink:href='#g2-44'/>
+<use x='196.478' y='162.131' xlink:href='#g2-49'/>
+<use x='199.124' y='162.131' xlink:href='#g2-52'/>
+<use x='201.771' y='162.131' xlink:href='#g2-52'/>
+<use x='204.417' y='162.131' xlink:href='#g2-71'/>
+<use x='207.946' y='162.131' xlink:href='#g2-98'/>
+<use x='168.285' y='168.109' xlink:href='#g2-50'/>
+<use x='170.931' y='168.109' xlink:href='#g4-2'/>
+<use x='178.092' y='168.109' xlink:href='#g2-49'/>
+<use x='180.738' y='168.109' xlink:href='#g2-56'/>
+<use x='183.385' y='168.109' xlink:href='#g2-45'/>
+<use x='185.149' y='168.109' xlink:href='#g2-99'/>
+<use x='187.501' y='168.109' xlink:href='#g2-111'/>
+<use x='190.001' y='168.109' xlink:href='#g2-114'/>
+<use x='191.808' y='168.109' xlink:href='#g2-101'/>
+<use x='195.925' y='168.109' xlink:href='#g2-73'/>
+<use x='197.395' y='168.109' xlink:href='#g2-110'/>
+<use x='200.128' y='168.109' xlink:href='#g2-116'/>
+<use x='202.039' y='168.109' xlink:href='#g2-101'/>
+<use x='204.391' y='168.109' xlink:href='#g2-108'/>
+<use x='207.418' y='168.109' xlink:href='#g2-88'/>
+<use x='210.947' y='168.109' xlink:href='#g2-101'/>
+<use x='213.299' y='168.109' xlink:href='#g2-111'/>
+<use x='215.945' y='168.109' xlink:href='#g2-110'/>
+<use x='220.442' y='168.109' xlink:href='#g2-64'/>
+<use x='223.971' y='168.109' xlink:href='#g2-51'/>
+<use x='226.617' y='168.109' xlink:href='#g2-71'/>
+<use x='230.146' y='168.109' xlink:href='#g2-104'/>
+<use x='232.879' y='168.109' xlink:href='#g2-122'/>
+<use x='168.285' y='174.086' xlink:href='#g2-85'/>
+<use x='171.917' y='174.086' xlink:href='#g2-98'/>
+<use x='174.65' y='174.086' xlink:href='#g2-117'/>
+<use x='177.383' y='174.086' xlink:href='#g2-110'/>
+<use x='180.116' y='174.086' xlink:href='#g2-116'/>
+<use x='182.027' y='174.086' xlink:href='#g2-117'/>
+<use x='186.524' y='174.086' xlink:href='#g2-50'/>
+<use x='189.17' y='174.086' xlink:href='#g2-48'/>
+<use x='191.817' y='174.086' xlink:href='#g2-46'/>
+<use x='193.287' y='174.086' xlink:href='#g2-48'/>
+<use x='195.933' y='174.086' xlink:href='#g2-52'/>
+<use x='198.58' y='174.086' xlink:href='#g2-44'/>
+<use x='201.814' y='174.086' xlink:href='#g2-71'/>
+<use x='205.343' y='174.086' xlink:href='#g2-67'/>
+<use x='208.724' y='174.086' xlink:href='#g2-67'/>
+<use x='213.87' y='174.086' xlink:href='#g2-57'/>
+<use x='216.516' y='174.086' xlink:href='#g2-46'/>
+<use x='217.986' y='174.086' xlink:href='#g2-51'/>
+<use x='220.633' y='174.086' xlink:href='#g2-46'/>
+<use x='222.103' y='174.086' xlink:href='#g2-48'/>
+<use x='224.749' y='174.086' xlink:href='#g2-44'/>
+<use x='227.984' y='174.086' xlink:href='#g2-103'/>
+<use x='230.63' y='174.086' xlink:href='#g2-108'/>
+<use x='231.893' y='174.086' xlink:href='#g2-105'/>
+<use x='233.155' y='174.086' xlink:href='#g2-98'/>
+<use x='236.035' y='174.086' xlink:href='#g2-99'/>
+<use x='240.152' y='174.086' xlink:href='#g2-50'/>
+<use x='242.798' y='174.086' xlink:href='#g2-46'/>
+<use x='244.268' y='174.086' xlink:href='#g2-51'/>
+<use x='246.915' y='174.086' xlink:href='#g2-49'/>
+<use x='249.561' y='174.086' xlink:href='#g2-44'/>
+<use x='252.796' y='174.086' xlink:href='#g2-99'/>
+<use x='255.148' y='174.086' xlink:href='#g2-108'/>
+<use x='256.41' y='174.086' xlink:href='#g2-97'/>
+<use x='258.953' y='174.086' xlink:href='#g2-110'/>
+<use x='261.686' y='174.086' xlink:href='#g2-103'/>
+<use x='266.097' y='174.086' xlink:href='#g2-49'/>
+<use x='268.743' y='174.086' xlink:href='#g2-48'/>
+<use x='271.389' y='174.086' xlink:href='#g2-46'/>
+<use x='272.859' y='174.086' xlink:href='#g2-48'/>
+<use x='275.506' y='174.086' xlink:href='#g2-46'/>
+<use x='276.976' y='174.086' xlink:href='#g2-48'/>
+<use x='168.285' y='180.064' xlink:href='#g2-55'/>
+<use x='170.931' y='180.064' xlink:href='#g2-50'/>
+<use x='175.342' y='180.064' xlink:href='#g2-108'/>
+<use x='176.604' y='180.064' xlink:href='#g2-111'/>
+<use x='179.251' y='180.064' xlink:href='#g2-103'/>
+<use x='181.897' y='180.064' xlink:href='#g2-105'/>
+<use x='183.16' y='180.064' xlink:href='#g2-99'/>
+<use x='185.512' y='180.064' xlink:href='#g2-97'/>
+<use x='188.055' y='180.064' xlink:href='#g2-108'/>
+<use x='191.082' y='180.064' xlink:href='#g2-99'/>
+<use x='193.434' y='180.064' xlink:href='#g2-111'/>
+<use x='195.933' y='180.064' xlink:href='#g2-114'/>
+<use x='197.741' y='180.064' xlink:href='#g2-101'/>
+<use x='200.093' y='180.064' xlink:href='#g2-115'/>
+<use x='203.886' y='180.064' xlink:href='#g2-111'/>
+<use x='206.533' y='180.064' xlink:href='#g2-110'/>
+<use x='211.03' y='180.064' xlink:href='#g2-50'/>
+<use x='215.44' y='180.064' xlink:href='#g2-110'/>
+<use x='218.173' y='180.064' xlink:href='#g2-117'/>
+<use x='220.906' y='180.064' xlink:href='#g2-109'/>
+<use x='225.109' y='180.064' xlink:href='#g2-97'/>
+<use x='229.416' y='180.064' xlink:href='#g2-110'/>
+<use x='232.149' y='180.064' xlink:href='#g2-111'/>
+<use x='234.942' y='180.064' xlink:href='#g2-100'/>
+<use x='237.675' y='180.064' xlink:href='#g2-101'/>
+<use x='240.027' y='180.064' xlink:href='#g2-115'/>
+<use x='168.285' y='186.041' xlink:href='#g2-50'/>
+<use x='170.931' y='186.041' xlink:href='#g2-48'/>
+<use x='173.578' y='186.041' xlink:href='#g2-50'/>
+<use x='176.224' y='186.041' xlink:href='#g2-49'/>
+<use x='178.87' y='186.041' xlink:href='#g2-45'/>
+<use x='180.635' y='186.041' xlink:href='#g2-48'/>
+<use x='183.281' y='186.041' xlink:href='#g2-49'/>
+<use x='185.927' y='186.041' xlink:href='#g2-45'/>
+<use x='187.692' y='186.041' xlink:href='#g2-51'/>
+<use x='190.338' y='186.041' xlink:href='#g2-48'/>
+<use x='192.984' y='186.041' xlink:href='#g2-41'/>
+</g>
+<g transform='matrix(0 -1 1 0 -42.661 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 16.008 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 74.677 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 133.346 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 192.015 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 250.684 341.611)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -37.431 342.148)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.238 341.275)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 79.907 343.087)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 138.576 342.014)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 197.245 337.719)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 255.914 341.745)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -32.2 325.505)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-50'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.469 321.144)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-51'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 85.138 346.107)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 143.807 365.769)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-54'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 202.476 381.942)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-52'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 261.145 301.817)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -26.97 345.906)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.699 338.189)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 90.368 343.423)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 149.037 355.166)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-56'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 207.706 357.247)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-55'/>
+<use x='175.048' y='186.041' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 266.375 306.649)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 -21.739 341.007)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 36.93 332.015)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 95.599 338.725)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 154.268 357.314)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-55'/>
+<use x='175.048' y='186.041' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 212.937 344.161)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 271.606 339.732)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 -16.509 341.678)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 42.16 306.179)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 100.829 334.9)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 159.498 317.99)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-51'/>
+<use x='175.048' y='186.041' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 218.167 334.565)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 276.836 334.095)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 -11.278 339.195)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 47.391 341.544)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 106.06 328.257)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-50'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 164.729 322.687)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-50'/>
+<use x='175.048' y='186.041' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 223.398 240.952)'>
+<use x='163.396' y='186.041' xlink:href='#g4-1'/>
+<use x='166.901' y='186.041' xlink:href='#g4-1'/>
+<use x='170.407' y='186.041' xlink:href='#g4-1'/>
+<use x='173.912' y='186.041' xlink:href='#g2-57'/>
+<use x='176.558' y='186.041' xlink:href='#g2-46'/>
+<use x='178.029' y='186.041' xlink:href='#g2-54'/>
+<use x='180.675' y='186.041' xlink:href='#g2-56'/>
+<use x='183.321' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 282.067 351.878)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-56'/>
+<use x='175.048' y='186.041' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -6.048 329.465)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 52.621 240.952)'>
+<use x='163.396' y='186.041' xlink:href='#g4-1'/>
+<use x='166.901' y='186.041' xlink:href='#g4-1'/>
+<use x='170.407' y='186.041' xlink:href='#g4-1'/>
+<use x='173.912' y='186.041' xlink:href='#g2-50'/>
+<use x='176.558' y='186.041' xlink:href='#g2-46'/>
+<use x='178.029' y='186.041' xlink:href='#g2-54'/>
+<use x='180.675' y='186.041' xlink:href='#g2-50'/>
+<use x='183.321' y='186.041' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 111.29 305.172)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-53'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 169.959 328.794)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 228.628 381.472)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-52'/>
+<use x='175.048' y='186.041' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 287.297 322.419)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-50'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 -.818 338.793)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 57.851 331.142)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-49'/>
+<use x='175.048' y='186.041' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 116.52 313.628)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-52'/>
+<use x='175.048' y='186.041' xlink:href='#g2-50'/>
+</g>
+<g transform='matrix(0 -1 1 0 175.189 275.511)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 233.858 350.469)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-56'/>
+<use x='175.048' y='186.041' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 292.527 352.482)'>
+<use x='168.285' y='186.041' xlink:href='#g2-48'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-56'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 4.413 341.544)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 63.082 275.176)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-57'/>
+<use x='175.048' y='186.041' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 121.751 326.177)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-50'/>
+<use x='175.048' y='186.041' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 180.42 318.661)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-51'/>
+<use x='175.048' y='186.041' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 239.089 336.578)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 297.758 338.457)'>
+<use x='168.285' y='186.041' xlink:href='#g2-49'/>
+<use x='170.931' y='186.041' xlink:href='#g2-46'/>
+<use x='172.401' y='186.041' xlink:href='#g2-48'/>
+<use x='175.048' y='186.041' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -72.883 382.933)'>
+<use x='168.285' y='186.041' xlink:href='#g1-82'/>
+<use x='174.255' y='186.041' xlink:href='#g1-101'/>
+<use x='178.351' y='186.041' xlink:href='#g1-108'/>
+<use x='180.551' y='186.041' xlink:href='#g1-97'/>
+<use x='184.979' y='186.041' xlink:href='#g1-116'/>
+<use x='188.307' y='186.041' xlink:href='#g1-105'/>
+<use x='190.507' y='186.041' xlink:href='#g1-118'/>
+<use x='194.755' y='186.041' xlink:href='#g1-101'/>
+<use x='201.922' y='186.041' xlink:href='#g1-114'/>
+<use x='205.07' y='186.041' xlink:href='#g1-115'/>
+<use x='208.603' y='186.041' xlink:href='#g1-115'/>
+<use x='215.207' y='186.041' xlink:href='#g3-40'/>
+<use x='218.5' y='186.041' xlink:href='#g3-108'/>
+<use x='220.521' y='186.041' xlink:href='#g3-111'/>
+<use x='224.52' y='186.041' xlink:href='#g3-119'/>
+<use x='230.068' y='186.041' xlink:href='#g3-101'/>
+<use x='233.832' y='186.041' xlink:href='#g3-114'/>
+<use x='239.547' y='186.041' xlink:href='#g3-105'/>
+<use x='241.567' y='186.041' xlink:href='#g3-115'/>
+<use x='247.636' y='186.041' xlink:href='#g3-98'/>
+<use x='252.244' y='186.041' xlink:href='#g3-101'/>
+<use x='256.008' y='186.041' xlink:href='#g3-116'/>
+<use x='259.066' y='186.041' xlink:href='#g3-116'/>
+<use x='262.124' y='186.041' xlink:href='#g3-101'/>
+<use x='265.887' y='186.041' xlink:href='#g3-114'/>
+<use x='268.779' y='186.041' xlink:href='#g3-41'/>
+</g>
+<path d='M136.149 307.031H346.746V277.031H136.149Z' fill='#fff'/>
+<path d='M136.149 307.031H346.746V277.031H136.149Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<path d='M139.336 287.523H142.324V279.551H139.336ZM145.313 287.523H148.301V281.543H145.313Z' fill='#fff'/>
+<path d='M139.336 287.523H142.324V279.551H139.336ZM145.313 287.523H148.301V281.543H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.354 114.479)'>
+<use x='191.843' y='173.035' xlink:href='#g3-120'/>
+<use x='195.745' y='173.035' xlink:href='#g3-109'/>
+<use x='202.47' y='173.035' xlink:href='#g3-105'/>
+<use x='204.49' y='173.035' xlink:href='#g3-58'/>
+<use x='206.843' y='173.035' xlink:href='#g0-54'/>
+<use x='210.548' y='173.035' xlink:href='#g0-56'/>
+</g>
+<path d='M177.086 287.523H180.074V279.551H177.086ZM183.063 287.523H186.055V281.543H183.063Z' fill='#f0e0f0'/>
+<path d='M177.086 287.523H180.074V279.551H177.086ZM183.063 287.523H186.055V281.543H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -38.403 114.479)'>
+<use x='233.123' y='173.035' xlink:href='#g3-109'/>
+<use x='239.848' y='173.035' xlink:href='#g3-105'/>
+<use x='241.869' y='173.035' xlink:href='#g3-58'/>
+<use x='244.221' y='173.035' xlink:href='#g0-54'/>
+<use x='247.926' y='173.035' xlink:href='#g0-56'/>
+</g>
+<path d='M221.895 287.523H224.883V279.551H221.895ZM227.875 287.523H230.863V281.543H227.875Z' fill='#e1c2e1'/>
+<path d='M221.895 287.523H224.883V279.551H221.895ZM227.875 287.523H230.863V281.543H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.441 114.036)'>
+<use x='277.134' y='173.035' xlink:href='#g3-116'/>
+<use x='280.192' y='173.035' xlink:href='#g3-99'/>
+<use x='283.956' y='173.035' xlink:href='#g3-58'/>
+<use x='286.308' y='173.035' xlink:href='#g0-55'/>
+<use x='290.013' y='173.035' xlink:href='#g0-50'/>
+</g>
+<path d='M265.109 287.523H268.098V279.551H265.109ZM271.086 287.523H274.074V281.543H271.086Z' fill='#d1a3d1'/>
+<path d='M265.109 287.523H268.098V279.551H265.109ZM271.086 287.523H274.074V281.543H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.04 114.479)'>
+<use x='319.615' y='173.035' xlink:href='#g3-106'/>
+<use x='321.871' y='173.035' xlink:href='#g3-101'/>
+<use x='325.634' y='173.035' xlink:href='#g3-58'/>
+<use x='327.987' y='173.035' xlink:href='#g0-55'/>
+<use x='331.691' y='173.035' xlink:href='#g0-49'/>
+</g>
+<path d='M306.859 287.523H309.848V279.551H306.859ZM312.836 287.523H315.824V281.543H312.836Z' fill='#c285c2'/>
+<path d='M306.859 287.523H309.848V279.551H306.859ZM312.836 287.523H315.824V281.543H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -39.932 114.515)'>
+<use x='359.038' y='173.035' xlink:href='#g3-116'/>
+<use x='362.096' y='173.035' xlink:href='#g3-98'/>
+<use x='366.469' y='173.035' xlink:href='#g3-98'/>
+<use x='370.842' y='173.035' xlink:href='#g3-58'/>
+<use x='373.194' y='173.035' xlink:href='#g0-54'/>
+<use x='376.899' y='173.035' xlink:href='#g0-51'/>
+</g>
+<path d='M139.336 300.527H142.324V292.559H139.336ZM145.313 300.527H148.301V294.551H145.313Z' fill='#b366b3'/>
+<path d='M139.336 300.527H142.324V292.559H139.336ZM145.313 300.527H148.301V294.551H145.313Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.662 114.036)'>
+<use x='191.843' y='186.041' xlink:href='#g3-114'/>
+<use x='194.735' y='186.041' xlink:href='#g3-112'/>
+<use x='199.108' y='186.041' xlink:href='#g3-58'/>
+<use x='201.46' y='186.041' xlink:href='#g0-52'/>
+<use x='205.165' y='186.041' xlink:href='#g0-50'/>
+</g>
+<path d='M177.086 300.527H180.074V292.559H177.086ZM183.063 300.527H186.055V294.551H183.063Z' fill='#a447a4'/>
+<path d='M177.086 300.527H180.074V292.559H177.086ZM183.063 300.527H186.055V294.551H183.063Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.882 114.515)'>
+<use x='233.123' y='186.041' xlink:href='#g3-104'/>
+<use x='237.496' y='186.041' xlink:href='#g3-111'/>
+<use x='241.73' y='186.041' xlink:href='#g3-97'/>
+<use x='245.563' y='186.041' xlink:href='#g3-114'/>
+<use x='248.455' y='186.041' xlink:href='#g3-100'/>
+<use x='252.828' y='186.041' xlink:href='#g3-58'/>
+<use x='255.18' y='186.041' xlink:href='#g0-53'/>
+<use x='258.885' y='186.041' xlink:href='#g0-51'/>
+</g>
+<path d='M221.895 300.527H224.883V292.559H221.895ZM227.875 300.527H230.863V294.551H227.875Z' fill='#942994'/>
+<path d='M221.895 300.527H224.883V292.559H221.895ZM227.875 300.527H230.863V294.551H227.875Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.084 114.515)'>
+<use x='277.134' y='186.041' xlink:href='#g3-109'/>
+<use x='283.859' y='186.041' xlink:href='#g3-101'/>
+<use x='287.622' y='186.041' xlink:href='#g3-115'/>
+<use x='290.869' y='186.041' xlink:href='#g3-104'/>
+<use x='295.241' y='186.041' xlink:href='#g3-58'/>
+<use x='297.593' y='186.041' xlink:href='#g0-53'/>
+<use x='301.298' y='186.041' xlink:href='#g0-50'/>
+</g>
+<path d='M265.109 300.527H268.098V292.559H265.109ZM271.086 300.527H274.074V294.551H271.086Z' fill='#850a85'/>
+<path d='M265.109 300.527H268.098V292.559H265.109ZM271.086 300.527H274.074V294.551H271.086Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -42.353 114.515)'>
+<use x='319.615' y='186.041' xlink:href='#g3-103'/>
+<use x='323.849' y='186.041' xlink:href='#g3-108'/>
+<use x='325.869' y='186.041' xlink:href='#g3-105'/>
+<use x='327.89' y='186.041' xlink:href='#g3-98'/>
+<use x='332.498' y='186.041' xlink:href='#g3-99'/>
+<use x='336.261' y='186.041' xlink:href='#g3-58'/>
+<use x='338.614' y='186.041' xlink:href='#g0-54'/>
+<use x='342.318' y='186.041' xlink:href='#g0-52'/>
+</g>
+<path d='M306.859 300.527H309.848V292.559H306.859ZM312.836 300.527H315.824V294.551H312.836Z' fill='#760076'/>
+<path d='M306.859 300.527H309.848V292.559H306.859ZM312.836 300.527H315.824V294.551H312.836Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.026 114.479)'>
+<use x='359.038' y='186.041' xlink:href='#g3-115'/>
+<use x='362.285' y='186.041' xlink:href='#g3-109'/>
+<use x='369.009' y='186.041' xlink:href='#g3-105'/>
+<use x='371.03' y='186.041' xlink:href='#g3-58'/>
+<use x='373.382' y='186.041' xlink:href='#g0-52'/>
+<use x='377.087' y='186.041' xlink:href='#g0-51'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg b/extlib/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg
new file mode 100644 (file)
index 0000000..ece6418
--- /dev/null
@@ -0,0 +1,766 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.9.1 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='315.585pt' height='208.604pt' viewBox='52.934 54.994 315.585 208.604'>
+<rect width="1000%" height="1000%" fill="white"/>
+<defs>
+<clipPath id='clip1'>
+<path d='M82.148 203.938H368.121V78.692H82.148Z'/>
+</clipPath>
+<use id='g2-44' xlink:href='#g0-44' transform='scale(.714)'/>
+<use id='g2-45' xlink:href='#g0-45' transform='scale(.714)'/>
+<use id='g2-46' xlink:href='#g0-46' transform='scale(.714)'/>
+<use id='g2-48' xlink:href='#g0-48' transform='scale(.714)'/>
+<use id='g2-49' xlink:href='#g0-49' transform='scale(.714)'/>
+<use id='g2-50' xlink:href='#g0-50' transform='scale(.714)'/>
+<use id='g2-51' xlink:href='#g0-51' transform='scale(.714)'/>
+<use id='g2-52' xlink:href='#g0-52' transform='scale(.714)'/>
+<use id='g2-53' xlink:href='#g0-53' transform='scale(.714)'/>
+<use id='g2-54' xlink:href='#g0-54' transform='scale(.714)'/>
+<use id='g2-55' xlink:href='#g0-55' transform='scale(.714)'/>
+<use id='g2-56' xlink:href='#g0-56' transform='scale(.714)'/>
+<use id='g2-57' xlink:href='#g0-57' transform='scale(.714)'/>
+<use id='g2-64' xlink:href='#g0-64' transform='scale(.714)'/>
+<use id='g2-65' xlink:href='#g0-65' transform='scale(.714)'/>
+<use id='g2-67' xlink:href='#g0-67' transform='scale(.714)'/>
+<use id='g2-71' xlink:href='#g0-71' transform='scale(.714)'/>
+<use id='g2-73' xlink:href='#g0-73' transform='scale(.714)'/>
+<use id='g2-79' xlink:href='#g0-79' transform='scale(.714)'/>
+<use id='g2-83' xlink:href='#g0-83' transform='scale(.714)'/>
+<use id='g2-97' xlink:href='#g0-97' transform='scale(.714)'/>
+<use id='g2-98' xlink:href='#g0-98' transform='scale(.714)'/>
+<use id='g2-99' xlink:href='#g0-99' transform='scale(.714)'/>
+<use id='g2-101' xlink:href='#g0-101' transform='scale(.714)'/>
+<use id='g2-103' xlink:href='#g0-103' transform='scale(.714)'/>
+<use id='g2-104' xlink:href='#g0-104' transform='scale(.714)'/>
+<use id='g2-105' xlink:href='#g0-105' transform='scale(.714)'/>
+<use id='g2-108' xlink:href='#g0-108' transform='scale(.714)'/>
+<use id='g2-109' xlink:href='#g0-109' transform='scale(.714)'/>
+<use id='g2-110' xlink:href='#g0-110' transform='scale(.714)'/>
+<use id='g2-111' xlink:href='#g0-111' transform='scale(.714)'/>
+<use id='g2-112' xlink:href='#g0-112' transform='scale(.714)'/>
+<use id='g2-114' xlink:href='#g0-114' transform='scale(.714)'/>
+<use id='g2-115' xlink:href='#g0-115' transform='scale(.714)'/>
+<use id='g2-116' xlink:href='#g0-116' transform='scale(.714)'/>
+<use id='g2-120' xlink:href='#g0-120' transform='scale(.714)'/>
+<use id='g2-122' xlink:href='#g0-122' transform='scale(.714)'/>
+<use id='g3-40' xlink:href='#g0-40' transform='scale(1.143)'/>
+<use id='g3-41' xlink:href='#g0-41' transform='scale(1.143)'/>
+<use id='g3-45' xlink:href='#g0-45' transform='scale(1.143)'/>
+<use id='g3-58' xlink:href='#g0-58' transform='scale(1.143)'/>
+<use id='g3-78' xlink:href='#g0-78' transform='scale(1.143)'/>
+<use id='g3-97' xlink:href='#g0-97' transform='scale(1.143)'/>
+<use id='g3-98' xlink:href='#g0-98' transform='scale(1.143)'/>
+<use id='g3-99' xlink:href='#g0-99' transform='scale(1.143)'/>
+<use id='g3-100' xlink:href='#g0-100' transform='scale(1.143)'/>
+<use id='g3-101' xlink:href='#g0-101' transform='scale(1.143)'/>
+<use id='g3-102' xlink:href='#g0-102' transform='scale(1.143)'/>
+<use id='g3-104' xlink:href='#g0-104' transform='scale(1.143)'/>
+<use id='g3-105' xlink:href='#g0-105' transform='scale(1.143)'/>
+<use id='g3-106' xlink:href='#g0-106' transform='scale(1.143)'/>
+<use id='g3-108' xlink:href='#g0-108' transform='scale(1.143)'/>
+<use id='g3-109' xlink:href='#g0-109' transform='scale(1.143)'/>
+<use id='g3-110' xlink:href='#g0-110' transform='scale(1.143)'/>
+<use id='g3-111' xlink:href='#g0-111' transform='scale(1.143)'/>
+<use id='g3-114' xlink:href='#g0-114' transform='scale(1.143)'/>
+<use id='g3-115' xlink:href='#g0-115' transform='scale(1.143)'/>
+<use id='g3-116' xlink:href='#g0-116' transform='scale(1.143)'/>
+<use id='g3-119' xlink:href='#g0-119' transform='scale(1.143)'/>
+<use id='g3-120' xlink:href='#g0-120' transform='scale(1.143)'/>
+<use id='g3-121' xlink:href='#g0-121' transform='scale(1.143)'/>
+<path id='g4-1' d='M1.445-1.245C1.445-1.41 1.305-1.549 1.141-1.549S.837-1.41 .837-1.245S.976-.941 1.141-.941S1.445-1.081 1.445-1.245Z'/>
+<path id='g1-82' d='M3.891-2.914C4.806-3.165 5.452-3.811 5.452-4.546C5.452-5.469 4.411-6.223 3.129-6.223H.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891-2.914ZM1.704-3.407V-5.694H3.022C4.062-5.694 4.671-5.192 4.671-4.546C4.671-3.963 4.125-3.407 3.022-3.407H1.704Z'/>
+<path id='g1-97' d='M3.694-2.591C3.694-3.479 3.04-4.133 2.152-4.133C1.569-4.133 1.139-3.981 .708-3.739L.762-3.102C1.21-3.434 1.65-3.569 2.143-3.569C2.645-3.569 2.95-3.165 2.95-2.582V-2.206C1.408-2.17 .395-1.766 .395-1.04C.395-.619 .672 .099 1.453 .099C1.632 .099 2.412 .081 2.977-.341V0H3.694V-2.591ZM2.95-1.255C2.95-1.067 2.95-.843 2.627-.655C2.403-.52 2.107-.484 1.928-.484C1.47-.484 1.085-.699 1.085-1.058C1.085-1.695 2.833-1.722 2.95-1.722V-1.255Z'/>
+<path id='g1-101' d='M3.829-1.964C3.829-2.242 3.82-2.923 3.47-3.461C3.093-4.026 2.52-4.133 2.179-4.133C1.139-4.133 .314-3.174 .314-2.026C.314-.843 1.193 .099 2.313 .099C2.744 .099 3.264-.009 3.784-.341L3.73-.959C3.165-.556 2.636-.484 2.322-.484C1.578-.484 1.004-1.139 .977-1.964H3.829ZM1.031-2.493C1.175-3.067 1.614-3.551 2.179-3.551C2.511-3.551 3.12-3.398 3.291-2.493H1.031Z'/>
+<path id='g1-105' d='M1.524-6.133H.664V-5.272H1.524V-6.133ZM1.453-3.981H.735V0H1.453V-3.981Z'/>
+<path id='g1-108' d='M1.453-6.223H.735V0H1.453V-6.223Z'/>
+<path id='g1-109' d='M6.581-2.663C6.581-3.327 6.402-4.08 5.317-4.08C4.564-4.08 4.142-3.622 3.927-3.344C3.865-3.524 3.676-4.08 2.762-4.08C2.053-4.08 1.623-3.667 1.417-3.398V-4.035H.726V0H1.47V-2.188C1.47-2.78 1.704-3.497 2.385-3.497C3.282-3.497 3.282-2.86 3.282-2.6V0H4.026V-2.188C4.026-2.78 4.259-3.497 4.94-3.497C5.837-3.497 5.837-2.86 5.837-2.6V0H6.581V-2.663Z'/>
+<path id='g1-116' d='M1.623-3.425H2.914V-3.981H1.623V-5.12H.959V-3.981H.17V-3.425H.933V-1.13C.933-.601 1.049 .099 1.704 .099C2.098 .099 2.564 .018 3.067-.233L2.914-.798C2.681-.619 2.367-.511 2.089-.511C1.739-.511 1.623-.825 1.623-1.291V-3.425Z'/>
+<path id='g1-118' d='M4.116-3.981H3.407L2.699-2.161C2.52-1.695 2.188-.825 2.143-.493H2.125C2.107-.646 2.08-.816 1.587-2.107C1.318-2.833 .879-3.927 .861-3.981H.126L1.704 0H2.537L4.116-3.981Z'/>
+<path id='g0-40' d='M2.127-5.23C2.008-5.23 1.995-5.23 1.911-5.154C1.032-4.387 .586-3.145 .586-1.743C.586-.425 .983 .844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 .063C1.276-.481 1.193-1.053 1.193-1.743C1.193-4.156 2.322-5.112 2.462-5.23H2.127Z'/>
+<path id='g0-41' d='M.746 1.743C.865 1.743 .879 1.743 .962 1.667C1.841 .9 2.287-.342 2.287-1.743C2.287-3.062 1.89-4.331 .969-5.14C.879-5.23 .865-5.23 .746-5.23H.411C.432-5.216 1.109-4.638 1.43-3.55C1.597-3.006 1.681-2.434 1.681-1.743C1.681 .669 .551 1.625 .411 1.743H.746Z'/>
+<path id='g0-44' d='M1.339-.007V-.628H.711V0H.907L.704 .893H1.018L1.339-.007Z'/>
+<path id='g0-45' d='M2.05-1.332V-1.771H.084V-1.332H2.05Z'/>
+<path id='g0-46' d='M1.339-.628H.711V0H1.339V-.628Z'/>
+<path id='g0-48' d='M3.403-2.267C3.403-2.601 3.403-3.417 3.075-3.989C2.72-4.617 2.183-4.721 1.848-4.721C1.534-4.721 .99-4.624 .642-4.024C.307-3.466 .293-2.706 .293-2.267C.293-1.75 .321-1.116 .614-.586C.921-.021 1.437 .146 1.848 .146C2.545 .146 2.929-.258 3.138-.697C3.382-1.193 3.403-1.834 3.403-2.267ZM1.848-.314C1.555-.314 1.22-.481 1.046-.983C.907-1.409 .9-1.848 .9-2.357C.9-2.999 .9-4.261 1.848-4.261S2.797-2.999 2.797-2.357C2.797-1.897 2.797-1.374 2.629-.928C2.434-.425 2.078-.314 1.848-.314Z'/>
+<path id='g0-49' d='M2.239-4.721H2.085C1.632-4.303 1.06-4.275 .642-4.261V-3.822C.914-3.829 1.262-3.843 1.611-3.982V-.439H.683V0H3.166V-.439H2.239V-4.721Z'/>
+<path id='g0-50' d='M1.974-.537C1.89-.537 1.806-.53 1.723-.53H.928L2.008-1.485C2.134-1.597 2.476-1.855 2.608-1.967C2.915-2.246 3.327-2.608 3.327-3.215C3.327-4.003 2.741-4.721 1.743-4.721C1.004-4.721 .544-4.324 .307-3.612L.635-3.201C.795-3.787 1.039-4.24 1.646-4.24C2.232-4.24 2.678-3.829 2.678-3.201C2.678-2.622 2.336-2.294 1.918-1.897C1.778-1.757 1.402-1.444 1.255-1.304C1.053-1.123 .572-.656 .37-.481V0H3.327V-.537H1.974Z'/>
+<path id='g0-51' d='M.697-3.578C.983-4.135 1.485-4.289 1.82-4.289C2.232-4.289 2.538-4.052 2.538-3.654C2.538-3.285 2.287-2.831 1.757-2.741C1.723-2.734 1.695-2.734 1.234-2.699V-2.239H1.778C2.441-2.239 2.685-1.716 2.685-1.276C2.685-.732 2.35-.314 1.806-.314C1.311-.314 .746-.551 .398-.997L.307-.544C.711-.091 1.276 .146 1.82 .146C2.734 .146 3.389-.537 3.389-1.269C3.389-1.841 2.929-2.301 2.378-2.462C2.908-2.734 3.18-3.201 3.18-3.654C3.18-4.247 2.573-4.721 1.827-4.721C1.213-4.721 .704-4.4 .411-3.982L.697-3.578Z'/>
+<path id='g0-52' d='M2.762-1.165H3.487V-1.625H2.762V-4.575H2.071L.209-1.625V-1.165H2.162V0H2.762V-1.165ZM.802-1.625C1.011-1.953 2.211-3.815 2.211-4.233V-1.625H.802Z'/>
+<path id='g0-53' d='M1.144-4.094H3.075V-4.575H.586V-1.967H1.095C1.262-2.343 1.59-2.511 1.904-2.511C2.19-2.511 2.622-2.315 2.622-1.43C2.622-.516 2.043-.314 1.688-.314C1.227-.314 .781-.558 .544-.955L.279-.537C.621-.112 1.137 .146 1.688 .146C2.608 .146 3.327-.565 3.327-1.416C3.327-2.28 2.685-2.971 1.918-2.971C1.618-2.971 1.353-2.866 1.144-2.692V-4.094Z'/>
+<path id='g0-54' d='M3.062-4.582C2.685-4.721 2.42-4.721 2.287-4.721C1.227-4.721 .307-3.724 .307-2.253C.307-.363 1.158 .146 1.862 .146C2.427 .146 2.72-.119 2.936-.342C3.382-.816 3.389-1.311 3.389-1.555C3.389-2.469 2.894-3.229 2.218-3.229C1.534-3.229 1.165-2.873 .962-2.671C1.053-3.626 1.541-4.289 2.294-4.289C2.434-4.289 2.713-4.275 3.062-4.142V-4.582ZM.969-1.534C.969-1.576 .969-1.681 .976-1.716C.976-2.19 1.276-2.769 1.897-2.769C2.748-2.769 2.748-1.792 2.748-1.555C2.748-1.29 2.748-.997 2.559-.704C2.392-.453 2.183-.314 1.862-.314C1.123-.314 1.004-1.227 .969-1.534Z'/>
+<path id='g0-55' d='M1.723-4.038C1.806-4.038 1.89-4.045 1.974-4.045H2.852C1.792-3.006 1.116-1.548 1.116 .07H1.771C1.771-1.967 2.762-3.431 3.389-4.087V-4.575H.307V-4.038H1.723Z'/>
+<path id='g0-56' d='M2.385-2.469C2.845-2.615 3.285-2.985 3.285-3.501C3.285-4.135 2.678-4.721 1.848-4.721S.411-4.135 .411-3.501C.411-2.978 .865-2.608 1.311-2.469C.697-2.28 .307-1.806 .307-1.269C.307-.523 .969 .146 1.848 .146S3.389-.523 3.389-1.269C3.389-1.806 2.992-2.28 2.385-2.469ZM1.848-2.699C1.353-2.699 .948-2.985 .948-3.494C.948-3.94 1.262-4.289 1.848-4.289C2.427-4.289 2.748-3.94 2.748-3.494C2.748-2.999 2.357-2.699 1.848-2.699ZM1.848-.314C1.367-.314 .941-.621 .941-1.276C.941-1.904 1.346-2.239 1.848-2.239S2.755-1.897 2.755-1.276C2.755-.621 2.322-.314 1.848-.314Z'/>
+<path id='g0-57' d='M.537-.174C.879 .077 1.193 .146 1.52 .146C2.497 .146 3.389-.837 3.389-2.336C3.389-4.24 2.545-4.721 1.876-4.721C1.255-4.721 .969-4.428 .767-4.226C.321-3.773 .307-3.292 .307-3.02C.307-2.12 .795-1.346 1.478-1.346C2.267-1.346 2.699-1.869 2.734-1.911C2.636-.802 2.092-.314 1.52-.314C1.158-.314 .934-.446 .774-.579L.537-.174ZM2.713-3.027C2.72-2.985 2.72-2.915 2.72-2.873C2.72-2.357 2.406-1.806 1.799-1.806C1.534-1.806 1.325-1.883 1.144-2.169C.962-2.441 .948-2.706 .948-3.02C.948-3.292 .948-3.605 1.165-3.912C1.311-4.122 1.52-4.289 1.869-4.289C2.545-4.289 2.692-3.473 2.713-3.027Z'/>
+<path id='g0-58' d='M1.339-3.096H.711V-2.469H1.339V-3.096ZM.711-.628V0H1.339V-.628H.711Z'/>
+<path id='g0-64' d='M4.142-.614C4.038-.614 4.024-.614 3.968-.586C3.626-.467 3.271-.391 2.901-.391C1.778-.391 .976-1.339 .976-2.42C.976-3.592 1.883-4.449 2.859-4.449C3.055-4.449 3.515-4.4 3.745-3.843C3.55-3.954 3.333-4.003 3.152-4.003C2.406-4.003 1.778-3.306 1.778-2.42C1.778-1.513 2.427-.837 3.145-.837C3.689-.837 4.519-1.276 4.519-2.518C4.519-3.222 4.47-4.91 2.866-4.91C1.541-4.91 .411-3.815 .411-2.42C.411-1.039 1.527 .07 2.873 .07C3.515 .07 4.115-.195 4.519-.614H4.142ZM3.152-1.297C2.72-1.297 2.343-1.778 2.343-2.42C2.343-3.082 2.734-3.543 3.145-3.543C3.578-3.543 3.954-3.062 3.954-2.42C3.954-1.757 3.564-1.297 3.152-1.297Z'/>
+<path id='g0-65' d='M2.803-4.84H2.127L.209 0H.781L1.325-1.381H3.445L3.989 0H4.721L2.803-4.84ZM2.392-4.31L3.271-1.792H1.499L2.392-4.31Z'/>
+<path id='g0-67' d='M4.317-.851C3.829-.551 3.605-.418 2.908-.418C1.827-.418 1.172-1.43 1.172-2.434C1.172-3.466 1.89-4.435 2.908-4.435C3.368-4.435 3.843-4.289 4.163-4.045L4.275-4.679C3.787-4.861 3.396-4.917 2.887-4.917C1.506-4.917 .474-3.773 .474-2.427C.474-.99 1.569 .07 2.929 .07C3.612 .07 3.898-.07 4.359-.321L4.317-.851Z'/>
+<path id='g0-71' d='M4.442-2.085H2.88V-1.625H3.829V-.558C3.522-.481 3.222-.418 2.908-.418C1.834-.418 1.172-1.43 1.172-2.427C1.172-3.382 1.82-4.435 2.873-4.435C3.515-4.435 3.919-4.24 4.268-3.947L4.38-4.582C3.898-4.812 3.473-4.924 2.943-4.924C1.534-4.924 .474-3.822 .474-2.427C.474-1.067 1.527 .07 2.901 .07C3.403 .07 3.996-.042 4.442-.272V-2.085Z'/>
+<path id='g0-73' d='M1.381-4.84H.676V0H1.381V-4.84Z'/>
+<path id='g0-78' d='M1.646-4.84H.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-.551H3.933L1.646-4.84Z'/>
+<path id='g0-79' d='M5.056-2.399C5.056-3.843 3.996-4.986 2.734-4.986S.411-3.843 .411-2.399S1.485 .146 2.734 .146C3.989 .146 5.056-.962 5.056-2.399ZM2.734-.349C1.89-.349 1.116-1.193 1.116-2.511C1.116-3.745 1.897-4.505 2.734-4.505S4.352-3.745 4.352-2.511C4.352-1.186 3.578-.349 2.734-.349Z'/>
+<path id='g0-83' d='M3.445-4.645C2.999-4.875 2.601-4.986 2.085-4.986C1.032-4.986 .411-4.275 .411-3.605C.411-3.32 .502-2.985 .844-2.664C1.151-2.378 1.471-2.308 1.904-2.204C2.49-2.064 2.65-2.029 2.852-1.82C2.985-1.688 3.096-1.492 3.096-1.255C3.096-.823 2.706-.377 2.029-.377C1.632-.377 .99-.495 .439-.962L.328-.335C.676-.133 1.255 .146 2.036 .146C3.006 .146 3.696-.558 3.696-1.339C3.696-1.904 3.368-2.225 3.229-2.371C2.936-2.657 2.615-2.734 2.078-2.859C1.653-2.957 1.43-3.013 1.262-3.173C1.172-3.264 1.011-3.424 1.011-3.689C1.011-4.08 1.402-4.484 2.078-4.484C2.608-4.484 2.978-4.317 3.333-4.017L3.445-4.645Z'/>
+<path id='g0-97' d='M2.971-2.008C2.971-2.72 2.427-3.201 1.736-3.201C1.297-3.201 .962-3.11 .572-2.901L.614-2.392C.844-2.545 1.186-2.755 1.736-2.755C2.043-2.755 2.364-2.525 2.364-2.001V-1.723C1.332-1.688 .314-1.471 .314-.823C.314-.474 .551 .07 1.165 .07C1.465 .07 2.015 .007 2.385-.265V0H2.971V-2.008ZM2.364-.99C2.364-.851 2.364-.669 2.12-.523C1.897-.398 1.625-.391 1.548-.391C1.165-.391 .872-.565 .872-.83C.872-1.276 2.05-1.318 2.364-1.332V-.99Z'/>
+<path id='g0-98' d='M1.179-4.84H.593V0H1.2V-.328C1.353-.195 1.688 .07 2.197 .07C2.957 .07 3.571-.642 3.571-1.555C3.571-2.399 3.089-3.166 2.392-3.166C1.953-3.166 1.527-3.027 1.179-2.769V-4.84ZM1.2-2.197C1.2-2.308 1.2-2.392 1.444-2.552C1.548-2.615 1.736-2.706 1.974-2.706C2.441-2.706 2.964-2.392 2.964-1.555C2.964-.704 2.385-.391 1.897-.391C1.639-.391 1.395-.509 1.2-.823V-2.197Z'/>
+<path id='g0-99' d='M3.034-.76C2.685-.537 2.308-.411 1.876-.411C1.234-.411 .858-.928 .858-1.555C.858-2.092 1.137-2.72 1.897-2.72C2.371-2.72 2.594-2.622 2.95-2.399L3.041-2.901C2.622-3.11 2.441-3.201 1.897-3.201C.851-3.201 .251-2.357 .251-1.548C.251-.697 .921 .07 1.869 .07C2.357 .07 2.776-.077 3.075-.251L3.034-.76Z'/>
+<path id='g0-100' d='M3.229-4.84H2.643V-2.797C2.197-3.124 1.743-3.166 1.541-3.166C.809-3.166 .251-2.434 .251-1.548S.802 .07 1.52 .07C1.953 .07 2.357-.126 2.622-.363V0H3.229V-4.84ZM2.622-.865C2.448-.579 2.183-.391 1.848-.391C1.36-.391 .858-.732 .858-1.541C.858-2.413 1.451-2.706 1.925-2.706C2.204-2.706 2.441-2.587 2.622-2.35V-.865Z'/>
+<path id='g0-101' d='M2.999-.76C2.608-.481 2.169-.391 1.869-.391C1.262-.391 .802-.886 .781-1.527H3.068C3.068-1.848 3.034-2.315 2.762-2.713C2.511-3.068 2.092-3.201 1.75-3.201C.9-3.201 .244-2.455 .244-1.569C.244-.676 .941 .07 1.862 .07C2.267 .07 2.685-.049 3.041-.265L2.999-.76ZM.83-1.946C.99-2.504 1.402-2.741 1.75-2.741C2.057-2.741 2.511-2.594 2.643-1.946H.83Z'/>
+<path id='g0-102' d='M1.325-2.657H2.12V-3.096H1.304V-3.898C1.304-4.38 1.743-4.449 1.974-4.449C2.12-4.449 2.308-4.428 2.566-4.331V-4.84C2.385-4.882 2.169-4.91 1.981-4.91C1.262-4.91 .739-4.394 .739-3.703V-3.096H.202V-2.657H.739V0H1.325V-2.657Z'/>
+<path id='g0-103' d='M3.508-3.166C3.354-3.166 2.887-3.159 2.357-2.957L2.343-2.95C2.092-3.117 1.848-3.166 1.646-3.166C.962-3.166 .453-2.629 .453-2.029C.453-1.785 .537-1.534 .697-1.339C.6-1.22 .495-1.025 .495-.76C.495-.488 .607-.314 .669-.23C.286-.007 .209 .314 .209 .481C.209 1.011 .941 1.43 1.848 1.43C2.762 1.43 3.487 1.011 3.487 .481C3.487-.502 2.267-.502 1.967-.502H1.318C1.206-.502 .907-.502 .907-.865C.907-1.004 .955-1.074 .962-1.088C1.206-.934 1.451-.886 1.639-.886C2.322-.886 2.831-1.423 2.831-2.022C2.831-2.246 2.769-2.448 2.643-2.636C2.615-2.678 2.615-2.685 2.615-2.692C2.615-2.72 3.034-2.72 3.068-2.72C3.075-2.72 3.34-2.72 3.592-2.692L3.508-3.166ZM1.646-1.318C1.269-1.318 .99-1.555 .99-2.022C.99-2.566 1.339-2.734 1.639-2.734C2.015-2.734 2.294-2.497 2.294-2.029C2.294-1.485 1.946-1.318 1.646-1.318ZM1.974 .042C2.134 .042 2.957 .042 2.957 .488C2.957 .788 2.434 .997 1.848 .997S.739 .788 .739 .488C.739 .453 .739 .042 1.304 .042H1.974Z'/>
+<path id='g0-104' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.625-3.166 1.304-2.817 1.165-2.671V-4.84H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-105' d='M1.227-4.784H.523V-4.08H1.227V-4.784ZM1.172-3.096H.586V0H1.172V-3.096Z'/>
+<path id='g0-106' d='M1.381-4.784H.676V-4.08H1.381V-4.784ZM-.453 1.186C-.133 1.36 .181 1.423 .446 1.423C.928 1.423 1.381 1.053 1.381 .411V-3.096H.795V.46C.795 .586 .795 .697 .649 .816C.488 .934 .293 .934 .23 .934C-.063 .934-.244 .802-.328 .725L-.453 1.186Z'/>
+<path id='g0-108' d='M1.172-4.84H.586V0H1.172V-4.84Z'/>
+<path id='g0-109' d='M5.3-2.064C5.3-2.608 5.14-3.166 4.282-3.166C3.696-3.166 3.333-2.824 3.166-2.601C3.096-2.79 2.922-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-1.695C3.243-2.155 3.438-2.706 3.975-2.706C4.693-2.706 4.693-2.218 4.693-2.015V0H5.3V-2.064Z'/>
+<path id='g0-110' d='M3.243-2.064C3.243-2.608 3.082-3.166 2.225-3.166C1.827-3.166 1.444-3.006 1.137-2.636V-3.145H.579V0H1.186V-1.695C1.186-2.155 1.381-2.706 1.918-2.706C2.636-2.706 2.636-2.218 2.636-2.015V0H3.243V-2.064Z'/>
+<path id='g0-111' d='M3.487-1.527C3.487-2.448 2.755-3.201 1.848-3.201S.209-2.441 .209-1.527C.209-.642 .948 .07 1.848 .07C2.755 .07 3.487-.642 3.487-1.527ZM1.848-.411C1.297-.411 .816-.816 .816-1.604S1.332-2.741 1.848-2.741C2.371-2.741 2.88-2.378 2.88-1.604C2.88-.809 2.385-.411 1.848-.411Z'/>
+<path id='g0-112' d='M1.2-.328C1.569 .007 1.967 .07 2.204 .07C2.943 .07 3.571-.635 3.571-1.555C3.571-2.392 3.11-3.166 2.42-3.166C2.106-3.166 1.583-3.075 1.179-2.762V-3.096H.593V1.353H1.2V-.328ZM1.2-2.315C1.36-2.511 1.632-2.685 1.967-2.685C2.525-2.685 2.964-2.169 2.964-1.555C2.964-.865 2.441-.391 1.897-.391C1.792-.391 1.618-.404 1.437-.551C1.227-.711 1.2-.816 1.2-.948V-2.315Z'/>
+<path id='g0-114' d='M1.179-1.485C1.179-2.239 1.806-2.643 2.42-2.65V-3.166C1.834-3.159 1.409-2.873 1.13-2.504V-3.145H.593V0H1.179V-1.485Z'/>
+<path id='g0-115' d='M2.545-2.985C2.071-3.18 1.723-3.201 1.471-3.201C1.297-3.201 .244-3.201 .244-2.273C.244-1.946 .425-1.764 .516-1.681C.76-1.437 1.053-1.381 1.423-1.311C1.75-1.248 2.127-1.179 2.127-.844C2.127-.404 1.548-.404 1.451-.404C1.004-.404 .586-.565 .307-.76L.209-.237C.446-.119 .872 .07 1.451 .07C1.764 .07 2.071 .021 2.329-.167C2.587-.363 2.671-.669 2.671-.907C2.671-1.032 2.657-1.304 2.364-1.569C2.106-1.799 1.855-1.848 1.52-1.911C1.109-1.988 .788-2.05 .788-2.357C.788-2.755 1.297-2.755 1.402-2.755C1.799-2.755 2.106-2.671 2.455-2.49L2.545-2.985Z'/>
+<path id='g0-116' d='M1.311-2.657H2.343V-3.096H1.311V-3.982H.774V-3.096H.139V-2.657H.753V-.893C.753-.425 .872 .07 1.374 .07S2.26-.091 2.469-.188L2.35-.635C2.12-.467 1.876-.411 1.681-.411C1.388-.411 1.311-.697 1.311-1.018V-2.657Z'/>
+<path id='g0-119' d='M4.951-3.096H4.407C4.345-2.901 3.954-1.723 3.738-.997C3.682-.795 3.612-.572 3.592-.411H3.585C3.543-.697 3.299-1.451 3.285-1.499L2.769-3.096H2.239C2.036-2.497 1.513-.934 1.458-.425H1.451C1.395-.921 .879-2.462 .767-2.797C.711-2.964 .711-2.978 .676-3.096H.105L1.123 0H1.709C1.716-.028 1.904-.579 2.148-1.353C2.253-1.695 2.462-2.364 2.497-2.671L2.504-2.678C2.518-2.532 2.559-2.378 2.608-2.204S2.706-1.841 2.755-1.681L3.292 0H3.933L4.951-3.096Z'/>
+<path id='g0-120' d='M1.932-1.597L3.285-3.096H2.671L1.681-1.953L.669-3.096H.042L1.437-1.597L0 0H.621L1.681-1.311L2.783 0H3.41L1.932-1.597Z'/>
+<path id='g0-121' d='M3.306-3.096H2.741C2.176-1.764 1.785-.865 1.757-.439C1.743-.635 1.618-.983 1.492-1.311C1.381-1.59 1.269-1.869 1.144-2.141L.704-3.096H.105L1.548 0C1.465 .202 1.325 .523 1.283 .614C1.137 .907 1.039 1.004 .851 1.004C.823 1.004 .565 1.004 .265 .879L.307 1.367C.37 1.381 .628 1.423 .844 1.423C1.123 1.423 1.374 1.318 1.667 .649L3.306-3.096Z'/>
+<path id='g0-122' d='M2.957-2.803V-3.096H.307V-2.65H1.332C1.416-2.65 1.499-2.657 1.583-2.657H2.127L.209-.307V0H2.978V-.467H1.897C1.813-.467 1.73-.46 1.646-.46H1.039L2.957-2.803Z'/>
+</defs>
+<g id='page1'>
+<path d='M139.344 212.797V203.938M196.539 212.797V203.938M253.734 212.797V203.938M310.926 212.797V203.938M139.344 69.836V78.692M196.539 69.836V78.692M253.734 69.836V78.692M310.926 69.836V78.692' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M110.746 208.192V203.938M167.941 208.192V203.938M225.137 208.192V203.938M282.332 208.192V203.938M339.524 208.192V203.938M110.746 74.442V78.692M167.941 74.442V78.692M225.137 74.442V78.692M282.332 74.442V78.692M339.524 74.442V78.692' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 203.938H86.402M82.148 172.629H86.402M82.148 141.317H86.402M82.148 110.004H86.402M82.148 78.692H86.402M368.121 203.938H363.871M368.121 172.629H363.871M368.121 141.317H363.871M368.121 110.004H363.871M368.121 78.692H363.871' stroke='#808080' fill='none' stroke-width='.199' stroke-miterlimit='10'/>
+<path d='M82.148 203.938V78.692H368.121V203.938H82.148Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -12.278 72.902)'>
+<use x='114.487' y='145.434' xlink:href='#g3-99'/>
+<use x='118.25' y='145.434' xlink:href='#g3-102'/>
+<use x='120.838' y='145.434' xlink:href='#g3-114'/>
+<use x='123.73' y='145.434' xlink:href='#g3-97'/>
+<use x='127.798' y='145.434' xlink:href='#g3-99'/>
+</g>
+<g transform='matrix(1 0 0 1 43.353 72.902)'>
+<use x='114.487' y='145.434' xlink:href='#g3-108'/>
+<use x='116.507' y='145.434' xlink:href='#g3-101'/>
+<use x='120.271' y='145.434' xlink:href='#g3-97'/>
+<use x='124.339' y='145.434' xlink:href='#g3-110'/>
+<use x='128.711' y='145.434' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 97.361 72.902)'>
+<use x='114.487' y='145.434' xlink:href='#g3-108'/>
+<use x='116.507' y='145.434' xlink:href='#g3-97'/>
+<use x='120.34' y='145.434' xlink:href='#g3-114'/>
+<use x='123.232' y='145.434' xlink:href='#g3-115'/>
+<use x='126.478' y='145.434' xlink:href='#g3-111'/>
+<use x='130.712' y='145.434' xlink:href='#g3-110'/>
+<use x='135.085' y='145.434' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 151.766 72.902)'>
+<use x='114.487' y='145.434' xlink:href='#g3-109'/>
+<use x='121.211' y='145.434' xlink:href='#g3-115'/>
+<use x='124.458' y='145.434' xlink:href='#g3-116'/>
+<use x='127.516' y='145.434' xlink:href='#g3-114'/>
+<use x='130.408' y='145.434' xlink:href='#g3-101'/>
+<use x='134.171' y='145.434' xlink:href='#g3-115'/>
+<use x='137.418' y='145.434' xlink:href='#g3-115'/>
+<use x='140.664' y='145.434' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 200.59 72.902)'>
+<use x='114.487' y='145.434' xlink:href='#g3-120'/>
+<use x='118.389' y='145.434' xlink:href='#g3-109'/>
+<use x='125.114' y='145.434' xlink:href='#g3-97'/>
+<use x='129.182' y='145.434' xlink:href='#g3-108'/>
+<use x='131.202' y='145.434' xlink:href='#g3-108'/>
+<use x='133.222' y='145.434' xlink:href='#g3-111'/>
+<use x='137.692' y='145.434' xlink:href='#g3-99'/>
+<use x='141.455' y='145.434' xlink:href='#g3-45'/>
+<use x='144.278' y='145.434' xlink:href='#g3-116'/>
+<use x='147.336' y='145.434' xlink:href='#g3-101'/>
+<use x='151.1' y='145.434' xlink:href='#g3-115'/>
+<use x='154.346' y='145.434' xlink:href='#g3-116'/>
+<use x='157.404' y='145.434' xlink:href='#g3-78'/>
+</g>
+<g transform='matrix(1 0 0 1 -40.942 60.139)'>
+<use x='114.487' y='145.434' xlink:href='#g2-48'/>
+<use x='117.133' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 28.828)'>
+<use x='114.487' y='145.434' xlink:href='#g2-48'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-53'/>
+<use x='121.25' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -2.484)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -33.795)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-53'/>
+<use x='121.25' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(1 0 0 1 -45.059 -65.107)'>
+<use x='114.487' y='145.434' xlink:href='#g2-50'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-120'/>
+</g>
+<path d='M82.148 141.317H368.121' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M96.051 203.938H99.289V141.317H96.051ZM153.246 203.938H156.484V141.317H153.246ZM210.442 203.938H213.68V141.317H210.442ZM267.637 203.938H270.875V141.317H267.637ZM324.828 203.938H328.067V141.317H324.828Z' fill='#933' clip-path='url(#clip1)'/>
+<path d='M96.051 203.938H99.289V141.317H96.051ZM153.246 203.938H156.484V141.317H153.246ZM210.442 203.938H213.68V141.317H210.442ZM267.637 203.938H270.875V141.317H267.637ZM324.828 203.938H328.067V141.317H324.828Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M97.672 141.317' fill='#933' clip-path='url(#clip1)'/>
+<path d='M95.68 141.317H99.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M97.672 141.317' fill='#933' clip-path='url(#clip1)'/>
+<path d='M95.68 141.317H99.664' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M154.867 141.317V141.067' fill='#933' clip-path='url(#clip1)'/>
+<path d='M154.867 141.317V141.067' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M152.871 141.066H156.859' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M154.867 141.317V141.567' fill='#933' clip-path='url(#clip1)'/>
+<path d='M154.867 141.317V141.567' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M156.86 141.566H152.875' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M212.059 141.317V141.067' fill='#933' clip-path='url(#clip1)'/>
+<path d='M212.059 141.317V141.067' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M210.066 141.066H214.05' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M212.059 141.317V141.567' fill='#933' clip-path='url(#clip1)'/>
+<path d='M212.059 141.317V141.567' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M214.054 141.566H210.066' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.254 141.317V141.254' fill='#933' clip-path='url(#clip1)'/>
+<path d='M269.254 141.317V141.254' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M267.262 141.254H271.246' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M269.254 141.317V141.379' fill='#933' clip-path='url(#clip1)'/>
+<path d='M269.254 141.317V141.379' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M271.246 141.379H267.262' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M326.449 141.317V141.067' fill='#933' clip-path='url(#clip1)'/>
+<path d='M326.449 141.317V141.067' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M324.457 141.066H328.441' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M326.449 141.317V141.567' fill='#933' clip-path='url(#clip1)'/>
+<path d='M326.449 141.317V141.567' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M328.441 141.566H324.457' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M101.281 203.938H104.52V142.067H101.281ZM158.477 203.938H161.715V140.817H158.477ZM215.672 203.938H218.91V143.696H215.672ZM272.867 203.938H276.106V141.442H272.867ZM330.059 203.938H333.297V138.122H330.059Z' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M101.281 203.938H104.52V142.067H101.281ZM158.477 203.938H161.715V140.817H158.477ZM215.672 203.938H218.91V143.696H215.672ZM272.867 203.938H276.106V141.442H272.867ZM330.059 203.938H333.297V138.122H330.059Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M102.902 142.067' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M100.91 142.066H104.895' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M102.902 142.067' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M100.91 142.066H104.895' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M160.098 140.817V140.563' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M160.098 140.817V140.563' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M158.101 140.562H162.089' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M160.098 140.817V141.067' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M160.098 140.817V141.067' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M162.09 141.066H158.105' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M217.289 143.696V143.508' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M217.289 143.696V143.508' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M215.297 143.507H219.282' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M217.289 143.696V143.883' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M217.289 143.696V143.883' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M219.285 143.883H215.297' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.484 141.442' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M272.492 141.442H276.476' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M274.484 141.442' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M272.492 141.442H276.476' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M331.68 138.122V138.059' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M331.68 138.122V138.059' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M329.688 138.058H333.672' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M331.68 138.122V138.184' fill='#bf8080' clip-path='url(#clip1)'/>
+<path d='M331.68 138.122V138.184' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M333.671 138.183H329.687' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M106.512 203.938H109.75V122.028H106.512ZM163.707 203.938H166.945V128.918H163.707ZM220.902 203.938H224.141V119.961H220.902ZM278.098 203.938H281.336V139.375H278.098ZM335.289 203.938H338.527V78.692H335.289Z' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M106.512 203.938H109.75V122.028H106.512ZM163.707 203.938H166.945V128.918H163.707ZM220.902 203.938H224.141V119.961H220.902ZM278.098 203.938H281.336V139.375H278.098ZM335.289 203.938H338.527V78.692H335.289Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.133 122.028' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M106.14 122.028H110.125' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M108.133 122.028' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M106.14 122.028H110.125' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M165.328 128.918V128.856' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M165.328 128.918V128.856' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M163.332 128.856H167.317' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M165.328 128.918V128.981' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M165.328 128.918V128.981' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M167.321 128.981H163.336' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M222.52 119.961V119.836' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M222.52 119.961V119.836' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M220.527 119.836H224.512' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M222.52 119.961V120.086' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M222.52 119.961V120.086' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M224.512 120.086H220.527' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.715 139.375V139.125' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M279.715 139.375V139.125' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M277.723 139.125H281.707' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M279.715 139.375V139.625' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M279.715 139.375V139.625' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M281.708 139.625H277.723' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M336.91 78.692' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M334.918 78.691H338.902' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M336.91 78.692' fill='#8080bf' clip-path='url(#clip1)'/>
+<path d='M334.918 78.691H338.902' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M111.742 203.938H114.981V120.086H111.742ZM168.938 203.938H172.176V136.43H168.938ZM226.133 203.938H229.371V136.809H226.133ZM283.328 203.938H286.567V78.692H283.328ZM340.52 203.938H343.758V112.571H340.52Z' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M111.742 203.938H114.981V120.086H111.742ZM168.938 203.938H172.176V136.43H168.938ZM226.133 203.938H229.371V136.809H226.133ZM283.328 203.938H286.567V78.692H283.328ZM340.52 203.938H343.758V112.571H340.52Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M113.363 120.086V119.899' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M113.363 120.086V119.899' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M111.371 119.899H115.356' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M113.363 120.086V120.274' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M113.363 120.086V120.274' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M115.356 120.273H111.371' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M170.559 136.43' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M168.562 136.43H172.547' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M170.559 136.43' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M168.562 136.43H172.547' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M227.75 136.809' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M225.758 136.809H229.743' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M227.75 136.809' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M225.758 136.809H229.743' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.945 78.692' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M282.953 78.691H286.937' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M284.945 78.692' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M282.953 78.691H286.937' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M342.141 112.571V112.383' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M342.141 112.571V112.383' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M340.149 112.383H344.133' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M342.141 112.571V112.758' fill='#ffb733' clip-path='url(#clip1)'/>
+<path d='M342.141 112.571V112.758' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M344.132 112.757H340.148' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M116.973 203.938H120.211V137.059H116.973ZM174.168 203.938H177.406V131.235H174.168ZM231.363 203.938H234.602V78.692H231.363ZM288.559 203.938H291.797V79.696H288.559ZM345.75 203.938H348.988V78.692H345.75Z' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M116.973 203.938H120.211V137.059H116.973ZM174.168 203.938H177.406V131.235H174.168ZM231.363 203.938H234.602V78.692H231.363ZM288.559 203.938H291.797V79.696H288.559ZM345.75 203.938H348.988V78.692H345.75Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M118.594 137.059V136.809' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M118.594 137.059V136.809' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M116.601 136.809H120.586' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M118.594 137.059V137.309' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M118.594 137.059V137.309' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M120.586 137.309H116.601' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M175.789 131.235V131.047' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M175.789 131.235V131.047' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M173.793 131.046H177.778' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M175.789 131.235V131.422' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M175.789 131.235V131.422' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M177.782 131.422H173.797' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M232.981 78.692' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M230.988 78.691H234.973' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M232.981 78.692' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M230.988 78.691H234.973' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.176 79.696V79.383' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M290.176 79.696V79.383' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M288.184 79.383H292.168' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M290.176 79.696V80.008' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M290.176 79.696V80.008' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M292.168 80.008H288.183' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M347.371 78.692' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M345.379 78.691H349.363' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M347.371 78.692' fill='#80bf80' clip-path='url(#clip1)'/>
+<path d='M345.379 78.691H349.363' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M122.203 203.938H125.441V78.692H122.203ZM179.399 203.938H182.637V93.286H179.399ZM236.594 203.938H239.832V78.692H236.594ZM293.789 203.938H297.024V78.692H293.789ZM350.981 203.938H354.219V78.692H350.981Z' fill='#399' clip-path='url(#clip1)'/>
+<path d='M122.203 203.938H125.441V78.692H122.203ZM179.399 203.938H182.637V93.286H179.399ZM236.594 203.938H239.832V78.692H236.594ZM293.789 203.938H297.024V78.692H293.789ZM350.981 203.938H354.219V78.692H350.981Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M123.824 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M121.832 78.691H125.817' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M123.824 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M121.832 78.691H125.817' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M181.02 93.286V93.161' fill='#399' clip-path='url(#clip1)'/>
+<path d='M181.02 93.286V93.161' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M179.023 93.16H183.008' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M181.02 93.286V93.411' fill='#399' clip-path='url(#clip1)'/>
+<path d='M181.02 93.286V93.411' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M183.012 93.41H179.027' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M238.211 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M236.219 78.691H240.204' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M238.211 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M236.219 78.691H240.204' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.406 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M293.414 78.691H297.398' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M295.406 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M293.414 78.691H297.398' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M352.602 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M350.609 78.691H354.593' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M352.602 78.692' fill='#399' clip-path='url(#clip1)'/>
+<path d='M350.609 78.691H354.593' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<path d='M263.02 263.2H367.922V229.188H263.02Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10' clip-path='url(#clip1)'/>
+<g transform='matrix(1 0 0 1 151.853 114.444)'>
+<use x='114.487' y='121.524' xlink:href='#g2-109'/>
+<use x='118.69' y='121.524' xlink:href='#g2-97'/>
+<use x='121.232' y='121.524' xlink:href='#g2-99'/>
+<use x='125.349' y='121.524' xlink:href='#g2-109'/>
+<use x='129.552' y='121.524' xlink:href='#g2-105'/>
+<use x='130.814' y='121.524' xlink:href='#g2-110'/>
+<use x='133.547' y='121.524' xlink:href='#g2-105'/>
+<use x='134.81' y='121.524' xlink:href='#g2-44'/>
+<use x='138.044' y='121.524' xlink:href='#g2-49'/>
+<use x='140.691' y='121.524' xlink:href='#g2-54'/>
+<use x='143.337' y='121.524' xlink:href='#g2-71'/>
+<use x='146.866' y='121.524' xlink:href='#g2-98'/>
+<use x='114.487' y='127.501' xlink:href='#g2-52'/>
+<use x='117.133' y='127.501' xlink:href='#g2-45'/>
+<use x='118.897' y='127.501' xlink:href='#g2-99'/>
+<use x='121.25' y='127.501' xlink:href='#g2-111'/>
+<use x='123.749' y='127.501' xlink:href='#g2-114'/>
+<use x='125.556' y='127.501' xlink:href='#g2-101'/>
+<use x='129.673' y='127.501' xlink:href='#g2-73'/>
+<use x='131.143' y='127.501' xlink:href='#g2-110'/>
+<use x='133.876' y='127.501' xlink:href='#g2-116'/>
+<use x='135.787' y='127.501' xlink:href='#g2-101'/>
+<use x='138.14' y='127.501' xlink:href='#g2-108'/>
+<use x='141.166' y='127.501' xlink:href='#g2-105'/>
+<use x='142.429' y='127.501' xlink:href='#g2-51'/>
+<use x='146.84' y='127.501' xlink:href='#g2-64'/>
+<use x='150.368' y='127.501' xlink:href='#g2-51'/>
+<use x='153.015' y='127.501' xlink:href='#g2-46'/>
+<use x='154.485' y='127.501' xlink:href='#g2-54'/>
+<use x='157.131' y='127.501' xlink:href='#g2-71'/>
+<use x='160.66' y='127.501' xlink:href='#g2-104'/>
+<use x='163.392' y='127.501' xlink:href='#g2-122'/>
+<use x='114.487' y='133.479' xlink:href='#g2-109'/>
+<use x='118.69' y='133.479' xlink:href='#g2-97'/>
+<use x='121.232' y='133.479' xlink:href='#g2-99'/>
+<use x='123.585' y='133.479' xlink:href='#g2-79'/>
+<use x='127.494' y='133.479' xlink:href='#g2-83'/>
+<use x='132.198' y='133.479' xlink:href='#g2-67'/>
+<use x='135.58' y='133.479' xlink:href='#g2-97'/>
+<use x='138.122' y='133.479' xlink:href='#g2-116'/>
+<use x='140.034' y='133.479' xlink:href='#g2-97'/>
+<use x='142.576' y='133.479' xlink:href='#g2-108'/>
+<use x='143.839' y='133.479' xlink:href='#g2-105'/>
+<use x='145.101' y='133.479' xlink:href='#g2-110'/>
+<use x='147.834' y='133.479' xlink:href='#g2-97'/>
+<use x='152.141' y='133.479' xlink:href='#g2-49'/>
+<use x='154.787' y='133.479' xlink:href='#g2-48'/>
+<use x='157.434' y='133.479' xlink:href='#g2-46'/>
+<use x='158.904' y='133.479' xlink:href='#g2-49'/>
+<use x='161.55' y='133.479' xlink:href='#g2-53'/>
+<use x='164.197' y='133.479' xlink:href='#g2-46'/>
+<use x='165.667' y='133.479' xlink:href='#g2-55'/>
+<use x='168.313' y='133.479' xlink:href='#g2-44'/>
+<use x='171.548' y='133.479' xlink:href='#g2-65'/>
+<use x='175.076' y='133.479' xlink:href='#g2-112'/>
+<use x='177.809' y='133.479' xlink:href='#g2-112'/>
+<use x='180.542' y='133.479' xlink:href='#g2-108'/>
+<use x='181.805' y='133.479' xlink:href='#g2-101'/>
+<use x='185.921' y='133.479' xlink:href='#g2-99'/>
+<use x='188.273' y='133.479' xlink:href='#g2-108'/>
+<use x='189.536' y='133.479' xlink:href='#g2-97'/>
+<use x='192.079' y='133.479' xlink:href='#g2-110'/>
+<use x='194.812' y='133.479' xlink:href='#g2-103'/>
+<use x='199.222' y='133.479' xlink:href='#g2-49'/>
+<use x='201.868' y='133.479' xlink:href='#g2-49'/>
+<use x='204.515' y='133.479' xlink:href='#g2-46'/>
+<use x='205.985' y='133.479' xlink:href='#g2-48'/>
+<use x='208.631' y='133.479' xlink:href='#g2-46'/>
+<use x='210.102' y='133.479' xlink:href='#g2-51'/>
+<use x='114.487' y='139.456' xlink:href='#g2-56'/>
+<use x='118.897' y='139.456' xlink:href='#g2-108'/>
+<use x='120.16' y='139.456' xlink:href='#g2-111'/>
+<use x='122.806' y='139.456' xlink:href='#g2-103'/>
+<use x='125.453' y='139.456' xlink:href='#g2-105'/>
+<use x='126.715' y='139.456' xlink:href='#g2-99'/>
+<use x='129.068' y='139.456' xlink:href='#g2-97'/>
+<use x='131.61' y='139.456' xlink:href='#g2-108'/>
+<use x='134.637' y='139.456' xlink:href='#g2-99'/>
+<use x='136.989' y='139.456' xlink:href='#g2-111'/>
+<use x='139.489' y='139.456' xlink:href='#g2-114'/>
+<use x='141.296' y='139.456' xlink:href='#g2-101'/>
+<use x='143.648' y='139.456' xlink:href='#g2-115'/>
+<use x='114.487' y='145.434' xlink:href='#g2-50'/>
+<use x='117.133' y='145.434' xlink:href='#g2-48'/>
+<use x='119.779' y='145.434' xlink:href='#g2-50'/>
+<use x='122.426' y='145.434' xlink:href='#g2-49'/>
+<use x='125.072' y='145.434' xlink:href='#g2-45'/>
+<use x='126.836' y='145.434' xlink:href='#g2-48'/>
+<use x='129.483' y='145.434' xlink:href='#g2-49'/>
+<use x='132.129' y='145.434' xlink:href='#g2-45'/>
+<use x='133.893' y='145.434' xlink:href='#g2-51'/>
+<use x='136.54' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -46.129 249.778)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 11.066 249.778)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 68.26 249.778)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 125.455 249.778)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 182.649 249.778)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 -40.898 250.529)'>
+<use x='114.487' y='145.434' xlink:href='#g2-48'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-57'/>
+<use x='121.25' y='145.434' xlink:href='#g2-57'/>
+</g>
+<g transform='matrix(0 -1 1 0 16.296 249.277)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 73.491 252.158)'>
+<use x='114.487' y='145.434' xlink:href='#g2-48'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-57'/>
+<use x='121.25' y='145.434' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 130.685 249.903)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 187.88 246.584)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-53'/>
+</g>
+<g transform='matrix(0 -1 1 0 -35.668 230.49)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-51'/>
+<use x='121.25' y='145.434' xlink:href='#g2-49'/>
+</g>
+<g transform='matrix(0 -1 1 0 21.527 237.378)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-50'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 78.721 228.423)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-51'/>
+<use x='121.25' y='145.434' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 135.916 247.837)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-51'/>
+</g>
+<g transform='matrix(0 -1 1 0 193.11 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-53'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-52'/>
+<use x='126.877' y='145.434' xlink:href='#g2-55'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -30.437 228.549)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-51'/>
+<use x='121.25' y='145.434' xlink:href='#g2-52'/>
+</g>
+<g transform='matrix(0 -1 1 0 26.757 244.893)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 83.952 245.269)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 141.146 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-51'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-50'/>
+<use x='126.877' y='145.434' xlink:href='#g2-49'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 198.34 221.034)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-52'/>
+<use x='121.25' y='145.434' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 -25.207 245.519)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-48'/>
+<use x='121.25' y='145.434' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 31.988 239.696)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-49'/>
+<use x='121.25' y='145.434' xlink:href='#g2-54'/>
+</g>
+<g transform='matrix(0 -1 1 0 89.182 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-50'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-49'/>
+<use x='126.877' y='145.434' xlink:href='#g2-52'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 146.376 188.157)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-57'/>
+<use x='121.25' y='145.434' xlink:href='#g2-56'/>
+</g>
+<g transform='matrix(0 -1 1 0 203.571 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-52'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-52'/>
+<use x='126.877' y='145.434' xlink:href='#g2-57'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -19.976 187.155)'>
+<use x='114.487' y='145.434' xlink:href='#g2-50'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-50'/>
+<use x='121.25' y='145.434' xlink:href='#g2-48'/>
+</g>
+<g transform='matrix(0 -1 1 0 37.218 201.746)'>
+<use x='114.487' y='145.434' xlink:href='#g2-49'/>
+<use x='117.133' y='145.434' xlink:href='#g2-46'/>
+<use x='118.603' y='145.434' xlink:href='#g2-55'/>
+<use x='121.25' y='145.434' xlink:href='#g2-55'/>
+</g>
+<g transform='matrix(0 -1 1 0 94.413 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-56'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-48'/>
+<use x='126.877' y='145.434' xlink:href='#g2-52'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 151.607 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-50'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-55'/>
+<use x='126.877' y='145.434' xlink:href='#g2-56'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 208.801 187.155)'>
+<use x='109.598' y='145.434' xlink:href='#g4-1'/>
+<use x='113.103' y='145.434' xlink:href='#g4-1'/>
+<use x='116.608' y='145.434' xlink:href='#g4-1'/>
+<use x='120.114' y='145.434' xlink:href='#g2-56'/>
+<use x='122.76' y='145.434' xlink:href='#g2-46'/>
+<use x='124.23' y='145.434' xlink:href='#g2-54'/>
+<use x='126.877' y='145.434' xlink:href='#g2-49'/>
+<use x='129.523' y='145.434' xlink:href='#g2-120'/>
+</g>
+<g transform='matrix(0 -1 1 0 -86.074 311.062)'>
+<use x='114.487' y='145.434' xlink:href='#g1-82'/>
+<use x='120.457' y='145.434' xlink:href='#g1-101'/>
+<use x='124.553' y='145.434' xlink:href='#g1-108'/>
+<use x='126.753' y='145.434' xlink:href='#g1-97'/>
+<use x='131.181' y='145.434' xlink:href='#g1-116'/>
+<use x='134.509' y='145.434' xlink:href='#g1-105'/>
+<use x='136.709' y='145.434' xlink:href='#g1-118'/>
+<use x='140.957' y='145.434' xlink:href='#g1-101'/>
+<use x='148.124' y='145.434' xlink:href='#g1-116'/>
+<use x='151.452' y='145.434' xlink:href='#g1-105'/>
+<use x='153.652' y='145.434' xlink:href='#g1-109'/>
+<use x='160.972' y='145.434' xlink:href='#g1-101'/>
+<use x='168.139' y='145.434' xlink:href='#g3-40'/>
+<use x='171.432' y='145.434' xlink:href='#g3-108'/>
+<use x='173.453' y='145.434' xlink:href='#g3-111'/>
+<use x='177.452' y='145.434' xlink:href='#g3-119'/>
+<use x='183' y='145.434' xlink:href='#g3-101'/>
+<use x='186.764' y='145.434' xlink:href='#g3-114'/>
+<use x='192.479' y='145.434' xlink:href='#g3-105'/>
+<use x='194.499' y='145.434' xlink:href='#g3-115'/>
+<use x='200.568' y='145.434' xlink:href='#g3-98'/>
+<use x='205.176' y='145.434' xlink:href='#g3-101'/>
+<use x='208.94' y='145.434' xlink:href='#g3-116'/>
+<use x='211.998' y='145.434' xlink:href='#g3-116'/>
+<use x='215.056' y='145.434' xlink:href='#g3-101'/>
+<use x='218.819' y='145.434' xlink:href='#g3-114'/>
+<use x='221.711' y='145.434' xlink:href='#g3-41'/>
+</g>
+<path d='M82.348 262.243H231.688V232.317H82.348Z' fill='#fff'/>
+<path d='M82.348 262.243H231.688V232.317H82.348Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<path d='M85.535 242.77H88.523V234.801H85.535ZM91.516 242.77H94.504V236.793H91.516Z' fill='#933'/>
+<path d='M85.535 242.77H88.523V234.801H85.535ZM91.516 242.77H94.504V236.793H91.516Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -40.354 110.298)'>
+<use x='141.573' y='132.464' xlink:href='#g3-120'/>
+<use x='145.475' y='132.464' xlink:href='#g3-109'/>
+<use x='152.2' y='132.464' xlink:href='#g3-105'/>
+<use x='154.221' y='132.464' xlink:href='#g3-58'/>
+<use x='156.573' y='132.464' xlink:href='#g0-57'/>
+<use x='160.278' y='132.464' xlink:href='#g0-48'/>
+</g>
+<path d='M130.344 242.77H133.336V234.801H130.344ZM136.324 242.77H139.313V236.793H136.324Z' fill='#bf8080'/>
+<path d='M130.344 242.77H133.336V234.801H130.344ZM136.324 242.77H139.313V236.793H136.324Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -38.403 110.298)'>
+<use x='181.727' y='132.464' xlink:href='#g3-109'/>
+<use x='188.452' y='132.464' xlink:href='#g3-105'/>
+<use x='190.472' y='132.464' xlink:href='#g3-58'/>
+<use x='192.825' y='132.464' xlink:href='#g0-57'/>
+<use x='196.53' y='132.464' xlink:href='#g0-51'/>
+</g>
+<path d='M165.844 242.77H168.832V234.801H165.844ZM171.82 242.77H174.813V236.793H171.82Z' fill='#8080bf'/>
+<path d='M165.844 242.77H168.832V234.801H165.844ZM171.82 242.77H174.813V236.793H171.82Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.441 109.855)'>
+<use x='215.44' y='132.464' xlink:href='#g3-116'/>
+<use x='218.498' y='132.464' xlink:href='#g3-99'/>
+<use x='222.262' y='132.464' xlink:href='#g3-58'/>
+<use x='224.614' y='132.464' xlink:href='#g0-53'/>
+<use x='228.319' y='132.464' xlink:href='#g0-48'/>
+</g>
+<path d='M197.77 242.77H200.758V234.801H197.77ZM203.75 242.77H206.738V236.793H203.75Z' fill='#ffb733'/>
+<path d='M197.77 242.77H200.758V234.801H197.77ZM203.75 242.77H206.738V236.793H203.75Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -37.04 110.298)'>
+<use x='246.965' y='132.464' xlink:href='#g3-106'/>
+<use x='249.221' y='132.464' xlink:href='#g3-101'/>
+<use x='252.984' y='132.464' xlink:href='#g3-58'/>
+<use x='255.337' y='132.464' xlink:href='#g0-53'/>
+<use x='259.041' y='132.464' xlink:href='#g0-51'/>
+</g>
+<path d='M85.535 255.742H88.523V247.77H85.535ZM91.516 255.742H94.504V249.762H91.516Z' fill='#80bf80'/>
+<path d='M85.535 255.742H88.523V247.77H85.535ZM91.516 255.742H94.504V249.762H91.516Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -43.882 110.334)'>
+<use x='141.573' y='145.434' xlink:href='#g3-104'/>
+<use x='145.946' y='145.434' xlink:href='#g3-111'/>
+<use x='150.18' y='145.434' xlink:href='#g3-97'/>
+<use x='154.013' y='145.434' xlink:href='#g3-114'/>
+<use x='156.905' y='145.434' xlink:href='#g3-100'/>
+<use x='161.278' y='145.434' xlink:href='#g3-58'/>
+<use x='163.63' y='145.434' xlink:href='#g0-53'/>
+<use x='167.335' y='145.434' xlink:href='#g0-51'/>
+</g>
+<path d='M130.344 255.742H133.336V247.77H130.344ZM136.324 255.742H139.313V249.762H136.324Z' fill='#399'/>
+<path d='M130.344 255.742H133.336V247.77H130.344ZM136.324 255.742H139.313V249.762H136.324Z' stroke='#000' fill='none' stroke-width='.399' stroke-miterlimit='10'/>
+<g transform='matrix(1 0 0 1 -39.227 109.855)'>
+<use x='181.727' y='145.434' xlink:href='#g3-115'/>
+<use x='184.974' y='145.434' xlink:href='#g3-121'/>
+<use x='188.876' y='145.434' xlink:href='#g3-115'/>
+<use x='192.122' y='145.434' xlink:href='#g3-58'/>
+<use x='194.474' y='145.434' xlink:href='#g0-50'/>
+<use x='198.179' y='145.434' xlink:href='#g0-51'/>
+</g>
+</g>
+</svg>
\ No newline at end of file
diff --git a/extlib/mimalloc/doc/doxyfile b/extlib/mimalloc/doc/doxyfile
new file mode 100644 (file)
index 0000000..73266f4
--- /dev/null
@@ -0,0 +1,2659 @@
+# Doxyfile 1.9.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single 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 configuration
+# 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
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = mi-malloc
+
+# 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         = 1.7/2.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           = mimalloc-logo.svg
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. 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 causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = 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.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION  = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, 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.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, 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.
+# The default value is: YES.
+
+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 and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# 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.
+# The default value is: NO.
+
+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.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, 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
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# 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.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+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 list of 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.
+# The default value is: NO.
+
+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-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = 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 Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+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 behavior. 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 behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+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.
+# The default value is: NO.
+
+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.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that act 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 (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+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.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+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.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# 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);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) 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.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# 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.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES 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.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = YES
+
+# When TYPEDEF_HIDES_STRUCT tag 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.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which efficively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
+#---------------------------------------------------------------------------
+# 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 respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+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. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If 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, only methods in the interface are
+# included.
+# The default value is: NO.
+
+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.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO 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.
+# The default value is: NO.
+
+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, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+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, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+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 then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES 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.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = 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 group names will
+# appear in their defined order.
+# The default value is: NO.
+
+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 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.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = 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.
+# The default value is: YES.
+
+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.
+# The default value is: YES.
+
+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.
+# The default value is: YES.
+
+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.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have 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 value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 0
+
+# 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.
+# The default value is: YES.
+
+SHOW_USED_FILES        = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = NO
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# 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 command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag 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.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag 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.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR          = 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)
+# The default value is: $file:$line: $text.
+
+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 standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is 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. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = mimalloc-doc.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
+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 patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
+# *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f \
+                         *.for \
+                         *.tcl \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# 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.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+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
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */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.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be 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:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> 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.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+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 information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# 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 that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES 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 documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = 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 https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES 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.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
+# YES then doxygen will add the directory of each input to the include path.
+# The default value is: YES.
+
+CLANG_ADD_INC_PATHS    = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH    =
+
+#---------------------------------------------------------------------------
+# 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.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# 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 a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+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.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = docs
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+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 left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = mimalloc-doxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 189
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 12
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 240
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = NO
+
+# 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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# 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 (see:
+# https://developer.apple.com/xcode/), 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. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset 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.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# 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.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see:
+# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# 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.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# 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.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# 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. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value 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
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# 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.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 180
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE      =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+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.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = \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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+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 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+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. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). 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.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# 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 too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+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.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+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 some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE        = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+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. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# 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 value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+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.
+# The default value is: NO.
+
+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.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# 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.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# 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.
+# The default value is: NO.
+
+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.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+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.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+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.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+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, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set 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.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+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.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+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.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+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 e.g.
+# 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.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+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 that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to 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.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. 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. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: 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. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+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.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_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.
+# The default value is: YES.
+
+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 (see:
+# http://www.graphviz.org/), 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 value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is 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 CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is 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.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+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.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES 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.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES 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.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is 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. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is 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. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is 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.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag 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.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+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).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The 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.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+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.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# 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).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to 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.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc and
+# plantuml temporary files.
+# The default value is: YES.
+
+DOT_CLEANUP            = YES
diff --git a/extlib/mimalloc/doc/ds-logo.jpg b/extlib/mimalloc/doc/ds-logo.jpg
new file mode 100644 (file)
index 0000000..c9abb1a
Binary files /dev/null and b/extlib/mimalloc/doc/ds-logo.jpg differ
diff --git a/extlib/mimalloc/doc/ds-logo.png b/extlib/mimalloc/doc/ds-logo.png
new file mode 100644 (file)
index 0000000..93b84e4
Binary files /dev/null and b/extlib/mimalloc/doc/ds-logo.png differ
diff --git a/extlib/mimalloc/doc/mimalloc-doc.h b/extlib/mimalloc/doc/mimalloc-doc.h
new file mode 100644 (file)
index 0000000..4de6085
--- /dev/null
@@ -0,0 +1,1281 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+
+#error "documentation file only!"
+
+
+/*! \mainpage
+
+This is the API documentation of the
+[mimalloc](https://github.com/microsoft/mimalloc) allocator
+(pronounced "me-malloc") -- a
+general purpose allocator with excellent [performance](bench.html)
+characteristics. Initially
+developed by Daan Leijen for the run-time systems of the
+[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages.
+
+It is a drop-in replacement for `malloc` and can be used in other programs
+without code changes, for example, on Unix you can use it as:
+```
+> LD_PRELOAD=/usr/bin/libmimalloc.so  myprogram
+```
+
+Notable aspects of the design include:
+
+- __small and consistent__: the library is about 8k LOC using simple and
+  consistent data structures. This makes it very suitable
+  to integrate and adapt in other projects. For runtime systems it
+  provides hooks for a monotonic _heartbeat_ and deferred freeing (for
+  bounded worst-case times with reference counting).
+- __free list sharding__: instead of one big free list (per size class) we have
+  many smaller lists per "mimalloc page" which reduces fragmentation and
+  increases locality --
+  things that are allocated close in time get allocated close in memory.
+  (A mimalloc page contains blocks of one size class and is usually 64KiB on a 64-bit system).
+- __free list multi-sharding__: the big idea! Not only do we shard the free list
+  per mimalloc page, but for each page we have multiple free lists. In particular, there
+  is one list for thread-local `free` operations, and another one for concurrent `free`
+  operations. Free-ing from another thread can now be a single CAS without needing
+  sophisticated coordination between threads. Since there will be 
+  thousands of separate free lists, contention is naturally distributed over the heap,
+  and the chance of contending on a single location will be low -- this is quite
+  similar to randomized algorithms like skip lists where adding
+  a random oracle removes the need for a more complex algorithm.
+- __eager page reset__: when a "page" becomes empty (with increased chance
+  due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged")
+  reducing (real) memory pressure and fragmentation, especially in long running
+  programs.
+- __secure__: _mimalloc_ can be build in secure mode, adding guard pages,
+  randomized allocation, encrypted free lists, etc. to protect against various
+  heap vulnerabilities. The performance penalty is only around 5% on average
+  over our benchmarks.
+- __first-class heaps__: efficiently create and use multiple heaps to allocate across different regions.
+  A heap can be destroyed at once instead of deallocating each object separately.
+- __bounded__: it does not suffer from _blowup_ \[1\], has bounded worst-case allocation
+  times (_wcat_), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes),
+  and has no internal points of contention using only atomic operations.
+- __fast__: In our benchmarks (see [below](#performance)),
+  _mimalloc_ outperforms all other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc),
+  and usually uses less memory (up to 25% more in the worst case). A nice property
+  is that it does consistently well over a wide range of benchmarks.
+
+You can read more on the design of _mimalloc_ in the
+[technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action)
+which also has detailed benchmark results.
+
+
+Further information:
+
+- \ref build
+- \ref using
+- \ref environment
+- \ref overrides
+- \ref bench
+- \ref malloc
+- \ref extended
+- \ref aligned
+- \ref heap
+- \ref typed
+- \ref analysis
+- \ref options
+- \ref posix
+- \ref cpp
+
+*/
+
+
+/// \defgroup malloc Basic Allocation
+/// The basic allocation interface.
+/// \{
+
+
+/// Free previously allocated memory.
+/// The pointer `p` must have been allocated before (or be \a NULL).
+/// @param p  pointer to free, or \a NULL.
+void  mi_free(void* p);
+
+/// Allocate \a size bytes.
+/// @param size  number of bytes to allocate.
+/// @returns pointer to the allocated memory or \a NULL if out of memory.
+/// Returns a unique pointer if called with \a size 0.
+void* mi_malloc(size_t size);
+
+/// Allocate zero-initialized `size` bytes.
+/// @param size The size in bytes.
+/// @returns Pointer to newly allocated zero initialized memory,
+/// or \a NULL if out of memory.
+void* mi_zalloc(size_t size);
+
+/// Allocate zero-initialized \a count elements of \a size bytes.
+/// @param count number of elements.
+/// @param size  size of each element.
+/// @returns pointer to the allocated memory
+/// of \a size*\a count bytes, or \a NULL if either out of memory
+/// or when `count*size` overflows.
+///
+/// Returns a unique pointer if called with either \a size or \a count of 0.
+/// @see mi_zalloc()
+void* mi_calloc(size_t count, size_t size);
+
+/// Re-allocate memory to \a newsize bytes.
+/// @param p  pointer to previously allocated memory (or \a NULL).
+/// @param newsize  the new required size in bytes.
+/// @returns pointer to the re-allocated memory
+/// of \a newsize bytes, or \a NULL if out of memory.
+/// If \a NULL is returned, the pointer \a p is not freed.
+/// Otherwise the original pointer is either freed or returned
+/// as the reallocated result (in case it fits in-place with the
+/// new size). If the pointer \a p is \a NULL, it behaves as
+/// \a mi_malloc(\a newsize). If \a newsize is larger than the
+/// original \a size allocated for \a p, the bytes after \a size
+/// are uninitialized.
+void* mi_realloc(void* p, size_t newsize);
+
+/// Re-allocate memory to \a count elements of \a size bytes, with extra memory initialized to zero.
+/// @param p Pointer to a previously allocated block (or \a NULL).
+/// @param count The number of elements.
+/// @param size The size of each element.
+/// @returns A pointer to a re-allocated block of \a count * \a size bytes, or \a NULL
+/// if out of memory or if \a count * \a size overflows.
+///
+/// If there is no overflow, it behaves exactly like `mi_rezalloc(p,count*size)`.
+/// @see mi_reallocn()
+/// @see [recallocarray()](http://man.openbsd.org/reallocarray) (on BSD).
+void* mi_recalloc(void* p, size_t count, size_t size);
+
+/// Try to re-allocate memory to \a newsize bytes _in place_.
+/// @param p  pointer to previously allocated memory (or \a NULL).
+/// @param newsize  the new required size in bytes.
+/// @returns pointer to the re-allocated memory
+/// of \a newsize bytes (always equal to \a p),
+/// or \a NULL if either out of memory or if
+/// the memory could not be expanded in place.
+/// If \a NULL is returned, the pointer \a p is not freed.
+/// Otherwise the original pointer is returned
+/// as the reallocated result since it fits in-place with the
+/// new size. If \a newsize is larger than the
+/// original \a size allocated for \a p, the bytes after \a size
+/// are uninitialized.
+void* mi_expand(void* p, size_t newsize);
+
+/// Allocate \a count elements of \a size bytes.
+/// @param count The number of elements.
+/// @param size The size of each element.
+/// @returns A pointer to a block of \a count * \a size bytes, or \a NULL
+/// if out of memory or if \a count * \a size overflows.
+///
+/// If there is no overflow, it behaves exactly like `mi_malloc(p,count*size)`.
+/// @see mi_calloc()
+/// @see mi_zallocn()
+void* mi_mallocn(size_t count, size_t size);
+
+/// Re-allocate memory to \a count elements of \a size bytes.
+/// @param p Pointer to a previously allocated block (or \a NULL).
+/// @param count The number of elements.
+/// @param size The size of each element.
+/// @returns A pointer to a re-allocated block of \a count * \a size bytes, or \a NULL
+/// if out of memory or if \a count * \a size overflows.
+///
+/// If there is no overflow, it behaves exactly like `mi_realloc(p,count*size)`.
+/// @see [reallocarray()](<http://man.openbsd.org/reallocarray>) (on BSD)
+void* mi_reallocn(void* p, size_t count, size_t size);
+
+/// Re-allocate memory to \a newsize bytes,
+/// @param p  pointer to previously allocated memory (or \a NULL).
+/// @param newsize  the new required size in bytes.
+/// @returns pointer to the re-allocated memory
+/// of \a newsize bytes, or \a NULL if out of memory.
+///
+/// In contrast to mi_realloc(), if \a NULL is returned, the original pointer
+/// \a p is freed (if it was not \a NULL itself).
+/// Otherwise the original pointer is either freed or returned
+/// as the reallocated result (in case it fits in-place with the
+/// new size). If the pointer \a p is \a NULL, it behaves as
+/// \a mi_malloc(\a newsize). If \a newsize is larger than the
+/// original \a size allocated for \a p, the bytes after \a size
+/// are uninitialized.
+///
+/// @see [reallocf](https://www.freebsd.org/cgi/man.cgi?query=reallocf) (on BSD)
+void* mi_reallocf(void* p, size_t newsize);
+
+
+/// Allocate and duplicate a string.
+/// @param s string to duplicate (or \a NULL).
+/// @returns a pointer to newly allocated memory initialized
+/// to string \a s, or \a NULL if either out of memory or if
+/// \a s is \a NULL.
+///
+/// Replacement for the standard [strdup()](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html)
+/// such that mi_free() can be used on the returned result.
+char* mi_strdup(const char* s);
+
+/// Allocate and duplicate a string up to \a n bytes.
+/// @param s string to duplicate (or \a NULL).
+/// @param n maximum number of bytes to copy (excluding the terminating zero).
+/// @returns a pointer to newly allocated memory initialized
+/// to string \a s up to the first \a n bytes (and always zero terminated),
+/// or \a NULL if either out of memory or if \a s is \a NULL.
+///
+/// Replacement for the standard [strndup()](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html)
+/// such that mi_free() can be used on the returned result.
+char* mi_strndup(const char* s, size_t n);
+
+/// Resolve a file path name.
+/// @param fname File name.
+/// @param resolved_name Should be \a NULL (but can also point to a buffer
+///                      of at least \a PATH_MAX bytes).
+/// @returns If successful a pointer to the resolved absolute file name, or
+/// \a NULL on failure (with \a errno set to the error code).
+///
+/// If \a resolved_name was \a NULL, the returned result should be freed with
+/// mi_free().
+///
+/// Replacement for the standard [realpath()](http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html)
+/// such that mi_free() can be used on the returned result (if \a resolved_name was \a NULL).
+char* mi_realpath(const char* fname, char* resolved_name);
+
+/// \}
+
+// ------------------------------------------------------
+// Extended functionality
+// ------------------------------------------------------
+
+/// \defgroup extended Extended Functions
+/// Extended functionality.
+/// \{
+
+/// Maximum size allowed for small allocations in
+/// #mi_malloc_small and #mi_zalloc_small (usually `128*sizeof(void*)` (= 1KB on 64-bit systems))
+#define MI_SMALL_SIZE_MAX   (128*sizeof(void*))
+
+/// Allocate a small object.
+/// @param size The size in bytes, can be at most #MI_SMALL_SIZE_MAX.
+/// @returns a pointer to newly allocated memory of at least \a size
+/// bytes, or \a NULL if out of memory.
+/// This function is meant for use in run-time systems for best
+/// performance and does not check if \a size was indeed small -- use
+/// with care!
+void* mi_malloc_small(size_t size);
+
+/// Allocate a zero initialized small object.
+/// @param size The size in bytes, can be at most #MI_SMALL_SIZE_MAX.
+/// @returns a pointer to newly allocated zero-initialized memory of at
+/// least \a size bytes, or \a NULL if out of memory.
+/// This function is meant for use in run-time systems for best
+/// performance and does not check if \a size was indeed small -- use
+/// with care!
+void* mi_zalloc_small(size_t size);
+
+/// Return the available bytes in a memory block.
+/// @param p Pointer to previously allocated memory (or \a NULL)
+/// @returns Returns the available bytes in the memory block, or
+/// 0 if \a p was \a NULL.
+///
+/// The returned size can be
+/// used to call \a mi_expand successfully.
+/// The returned size is always at least equal to the
+/// allocated size of \a p, and, in the current design,
+/// should be less than 16.7% more.
+///
+/// @see [_msize](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=vs-2017) (Windows)
+/// @see [malloc_usable_size](http://man7.org/linux/man-pages/man3/malloc_usable_size.3.html) (Linux)
+/// @see mi_good_size()
+size_t mi_usable_size(void* p);
+
+/// Return the used allocation size.
+/// @param size The minimal required size in bytes.
+/// @returns the size `n` that will be allocated, where `n >= size`.
+///
+/// Generally, `mi_usable_size(mi_malloc(size)) == mi_good_size(size)`.
+/// This can be used to reduce internal wasted space when
+/// allocating buffers for example.
+///
+/// @see mi_usable_size()
+size_t mi_good_size(size_t size);
+
+/// Eagerly free memory.
+/// @param force If \a true, aggressively return memory to the OS (can be expensive!)
+///
+/// Regular code should not have to call this function. It can be beneficial
+/// in very narrow circumstances; in particular, when a long running thread
+/// allocates a lot of blocks that are freed by other threads it may improve
+/// resource usage by calling this every once in a while.
+void   mi_collect(bool force);
+
+/// Deprecated
+/// @param out Ignored, outputs to the registered output function or stderr by default.
+///
+/// Most detailed when using a debug build.
+void mi_stats_print(void* out);
+
+/// Print the main statistics.
+/// @param out An output function or \a NULL for the default.
+/// @param arg Optional argument passed to \a out (if not \a NULL)
+///
+/// Most detailed when using a debug build.
+void mi_stats_print_out(mi_output_fun* out, void* arg);
+
+/// Reset statistics.
+void mi_stats_reset(void);
+
+/// Merge thread local statistics with the main statistics and reset.
+void mi_stats_merge(void);
+
+/// Initialize mimalloc on a thread.
+/// Should not be used as on most systems (pthreads, windows) this is done
+/// automatically.
+void mi_thread_init(void);
+
+/// Uninitialize mimalloc on a thread.
+/// Should not be used as on most systems (pthreads, windows) this is done
+/// automatically. Ensures that any memory that is not freed yet (but will
+/// be freed by other threads in the future) is properly handled.
+void mi_thread_done(void);
+
+/// Print out heap statistics for this thread.
+/// @param out An output function or \a NULL for the default.
+/// @param arg Optional argument passed to \a out (if not \a NULL)
+///
+/// Most detailed when using a debug build.
+void mi_thread_stats_print_out(mi_output_fun* out, void* arg);
+
+/// Type of deferred free functions.
+/// @param force If \a true all outstanding items should be freed.
+/// @param heartbeat A monotonically increasing count.
+/// @param arg Argument that was passed at registration to hold extra state.
+///
+/// @see mi_register_deferred_free
+typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
+
+/// Register a deferred free function.
+/// @param deferred_free Address of a deferred free-ing function or \a NULL to unregister.
+/// @param arg Argument that will be passed on to the deferred free function.
+///
+/// Some runtime systems use deferred free-ing, for example when using
+/// reference counting to limit the worst case free time.
+/// Such systems can register (re-entrant) deferred free function
+/// to free more memory on demand. When the \a force parameter is
+/// \a true all possible memory should be freed.
+/// The per-thread \a heartbeat parameter is monotonically increasing
+/// and guaranteed to be deterministic if the program allocates
+/// deterministically. The \a deferred_free function is guaranteed
+/// to be called deterministically after some number of allocations
+/// (regardless of freeing or available free memory).
+/// At most one \a deferred_free function can be active.
+void   mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg);
+
+/// Type of output functions.
+/// @param msg Message to output.
+/// @param arg Argument that was passed at registration to hold extra state.
+///
+/// @see mi_register_output()
+typedef void (mi_output_fun)(const char* msg, void* arg);
+
+/// Register an output function.
+/// @param out The output function, use `NULL` to output to stderr.
+/// @param arg Argument that will be passed on to the output function.
+///
+/// The `out` function is called to output any information from mimalloc,
+/// like verbose or warning messages.
+void mi_register_output(mi_output_fun* out, void* arg);
+
+/// Type of error callback functions.
+/// @param err Error code (see mi_register_error() for a complete list).
+/// @param arg Argument that was passed at registration to hold extra state.
+///
+/// @see mi_register_error()
+typedef void (mi_error_fun)(int err, void* arg);
+
+/// Register an error callback function.
+/// @param errfun The error function that is called on an error (use \a NULL for default)
+/// @param arg Extra argument that will be passed on to the error function.
+///
+/// The \a errfun function is called on an error in mimalloc after emitting
+/// an error message (through the output function). It as always legal to just
+/// return from the \a errfun function in which case allocation functions generally
+/// return \a NULL or ignore the condition. The default function only calls abort()
+/// when compiled in secure mode with an \a EFAULT error. The possible error
+/// codes are:
+/// * \a EAGAIN: Double free was detected (only in debug and secure mode).
+/// * \a EFAULT: Corrupted free list or meta-data was detected (only in debug and secure mode).
+/// * \a ENOMEM: Not enough memory available to satisfy the request.
+/// * \a EOVERFLOW: Too large a request, for example in mi_calloc(), the \a count and \a size parameters are too large.
+/// * \a EINVAL: Trying to free or re-allocate an invalid pointer.
+void mi_register_error(mi_error_fun* errfun, void* arg);
+
+/// Is a pointer part of our heap?
+/// @param p The pointer to check.
+/// @returns \a true if this is a pointer into our heap.
+/// This function is relatively fast.
+bool mi_is_in_heap_region(const void* p);
+
+/// Reserve OS memory for use by mimalloc. Reserved areas are used
+/// before allocating from the OS again. By reserving a large area upfront, 
+/// allocation can be more efficient, and can be better managed on systems
+/// without `mmap`/`VirtualAlloc` (like WASM for example).
+/// @param size        The size to reserve.
+/// @param commit      Commit the memory upfront.
+/// @param allow_large Allow large OS pages (2MiB) to be used?
+/// @return \a 0 if successful, and an error code otherwise (e.g. `ENOMEM`).
+int  mi_reserve_os_memory(size_t size, bool commit, bool allow_large);
+
+/// Manage a particular memory area for use by mimalloc. 
+/// This is just like `mi_reserve_os_memory` except that the area should already be
+/// allocated in some manner and available for use my mimalloc.
+/// @param start       Start of the memory area
+/// @param size        The size of the memory area.
+/// @param commit      Is the area already committed?
+/// @param is_large    Does it consist of large OS pages? Set this to \a true as well for memory
+///                    that should not be decommitted or protected (like rdma etc.)
+/// @param is_zero     Does the area consists of zero's?
+/// @param numa_node   Possible associated numa node or `-1`.
+/// @return \a true if successful, and \a false on error.
+bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node);
+
+/// Reserve \a pages of huge OS pages (1GiB) evenly divided over \a numa_nodes nodes,
+/// but stops after at most `timeout_msecs` seconds.
+/// @param pages The number of 1GiB pages to reserve.
+/// @param numa_nodes The number of nodes do evenly divide the pages over, or 0 for using the actual number of NUMA nodes.
+/// @param timeout_msecs Maximum number of milli-seconds to try reserving, or 0 for no timeout.
+/// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out.
+///
+/// The reserved memory is used by mimalloc to satisfy allocations.
+/// May quit before \a timeout_msecs are expired if it estimates it will take more than
+/// 1.5 times \a timeout_msecs. The time limit is needed because on some operating systems
+/// it can take a long time to reserve contiguous memory if the physical memory is
+/// fragmented.
+int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs);
+
+/// Reserve \a pages of huge OS pages (1GiB) at a specific \a numa_node,
+/// but stops after at most `timeout_msecs` seconds.
+/// @param pages The number of 1GiB pages to reserve.
+/// @param numa_node The NUMA node where the memory is reserved (start at 0).
+/// @param timeout_msecs Maximum number of milli-seconds to try reserving, or 0 for no timeout.
+/// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out.
+///
+/// The reserved memory is used by mimalloc to satisfy allocations.
+/// May quit before \a timeout_msecs are expired if it estimates it will take more than
+/// 1.5 times \a timeout_msecs. The time limit is needed because on some operating systems
+/// it can take a long time to reserve contiguous memory if the physical memory is
+/// fragmented.
+int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs);
+
+
+/// Is the C runtime \a malloc API redirected?
+/// @returns \a true if all malloc API calls are redirected to mimalloc.
+///
+/// Currenty only used on Windows.
+bool mi_is_redirected();
+
+/// Return process information (time and memory usage).
+/// @param elapsed_msecs   Optional. Elapsed wall-clock time of the process in milli-seconds.
+/// @param user_msecs      Optional. User time in milli-seconds (as the sum over all threads).
+/// @param system_msecs    Optional. System time in milli-seconds.
+/// @param current_rss     Optional. Current working set size (touched pages).
+/// @param peak_rss        Optional. Peak working set size (touched pages).
+/// @param current_commit  Optional. Current committed memory (backed by the page file).
+/// @param peak_commit     Optional. Peak committed memory (backed by the page file).
+/// @param page_faults     Optional. Count of hard page faults.
+///
+/// The \a current_rss is precise on Windows and MacOSX; other systems estimate
+/// this using \a current_commit. The \a commit is precise on Windows but estimated
+/// on other systems as the amount of read/write accessible memory reserved by mimalloc.
+void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults);
+
+/// \}
+
+// ------------------------------------------------------
+// Aligned allocation
+// ------------------------------------------------------
+
+/// \defgroup aligned Aligned Allocation
+///
+/// Allocating aligned memory blocks.
+///
+/// \{
+
+/// The maximum supported alignment size (currently 1MiB).
+#define MI_ALIGNMENT_MAX   (1024*1024UL)   
+
+/// Allocate \a size bytes aligned by \a alignment.
+/// @param size  number of bytes to allocate.
+/// @param alignment  the minimal alignment of the allocated memory. Must be less than #MI_ALIGNMENT_MAX.
+/// @returns pointer to the allocated memory or \a NULL if out of memory.
+/// The returned pointer is aligned by \a alignment, i.e.
+/// `(uintptr_t)p % alignment == 0`.
+///
+/// Returns a unique pointer if called with \a size 0.
+/// @see [_aligned_malloc](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=vs-2017) (on Windows)
+/// @see [aligned_alloc](http://man.openbsd.org/reallocarray) (on BSD, with switched arguments!)
+/// @see [posix_memalign](https://linux.die.net/man/3/posix_memalign) (on Posix, with switched arguments!)
+/// @see [memalign](https://linux.die.net/man/3/posix_memalign) (on Linux, with switched arguments!)
+void* mi_malloc_aligned(size_t size, size_t alignment);
+void* mi_zalloc_aligned(size_t size, size_t alignment);
+void* mi_calloc_aligned(size_t count, size_t size, size_t alignment);
+void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment);
+
+/// Allocate \a size bytes aligned by \a alignment at a specified \a offset.
+/// @param size  number of bytes to allocate.
+/// @param alignment  the minimal alignment of the allocated memory at \a offset.
+/// @param offset     the offset that should be aligned.
+/// @returns pointer to the allocated memory or \a NULL if out of memory.
+/// The returned pointer is aligned by \a alignment at \a offset, i.e.
+/// `((uintptr_t)p + offset) % alignment == 0`.
+///
+/// Returns a unique pointer if called with \a size 0.
+/// @see [_aligned_offset_malloc](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-offset-malloc?view=vs-2017) (on Windows)
+void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset);
+void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset);
+void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset);
+void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset);
+
+/// \}
+
+/// \defgroup heap Heap Allocation
+///
+/// First-class heaps that can be destroyed in one go.
+///
+/// \{
+
+/// Type of first-class heaps.
+/// A heap can only be used for allocation in
+/// the thread that created this heap! Any allocated
+/// blocks can be freed or reallocated by any other thread though.
+struct mi_heap_s;
+
+/// Type of first-class heaps.
+/// A heap can only be used for (re)allocation in
+/// the thread that created this heap! Any allocated
+/// blocks can be freed by any other thread though.
+typedef struct mi_heap_s mi_heap_t;
+
+/// Create a new heap that can be used for allocation.
+mi_heap_t* mi_heap_new();
+
+/// Delete a previously allocated heap.
+/// This will release resources and migrate any
+/// still allocated blocks in this heap (efficienty)
+/// to the default heap.
+///
+/// If \a heap is the default heap, the default
+/// heap is set to the backing heap.
+void mi_heap_delete(mi_heap_t* heap);
+
+/// Destroy a heap, freeing all its still allocated blocks.
+/// Use with care as this will free all blocks still
+/// allocated in the heap. However, this can be a very
+/// efficient way to free all heap memory in one go.
+///
+/// If \a heap is the default heap, the default
+/// heap is set to the backing heap.
+void mi_heap_destroy(mi_heap_t* heap);
+
+/// Set the default heap to use for mi_malloc() et al.
+/// @param heap  The new default heap.
+/// @returns The previous default heap.
+mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
+
+/// Get the default heap that is used for mi_malloc() et al.
+/// @returns The current default heap.
+mi_heap_t* mi_heap_get_default();
+
+/// Get the backing heap.
+/// The _backing_ heap is the initial default heap for
+/// a thread and always available for allocations.
+/// It cannot be destroyed or deleted
+/// except by exiting the thread.
+mi_heap_t* mi_heap_get_backing();
+
+/// Release outstanding resources in a specific heap.
+void mi_heap_collect(mi_heap_t* heap, bool force);
+
+/// Allocate in a specific heap.
+/// @see mi_malloc()
+void* mi_heap_malloc(mi_heap_t* heap, size_t size);
+
+/// Allocate a small object in a specific heap.
+/// \a size must be smaller or equal to MI_SMALL_SIZE_MAX().
+/// @see mi_malloc()
+void* mi_heap_malloc_small(mi_heap_t* heap, size_t size);
+
+/// Allocate zero-initialized in a specific heap.
+/// @see mi_zalloc()
+void* mi_heap_zalloc(mi_heap_t* heap, size_t size);
+
+/// Allocate \a count zero-initialized elements in a specific heap.
+/// @see mi_calloc()
+void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size);
+
+/// Allocate \a count elements in a specific heap.
+/// @see mi_mallocn()
+void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size);
+
+/// Duplicate a string in a specific heap.
+/// @see mi_strdup()
+char* mi_heap_strdup(mi_heap_t* heap, const char* s);
+
+/// Duplicate a string of at most length \a n in a specific heap.
+/// @see mi_strndup()
+char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n);
+
+/// Resolve a file path name using a specific \a heap to allocate the result.
+/// @see mi_realpath()
+char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name);
+
+void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize);
+void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size);
+void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize);
+
+void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment);
+void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset);
+void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment);
+void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset);
+void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment);
+void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset);
+void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment);
+void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset);
+
+/// \}
+
+
+/// \defgroup zeroinit Zero initialized re-allocation
+///
+/// The zero-initialized re-allocations are only valid on memory that was
+/// originally allocated with zero initialization too.
+/// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
+/// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
+///
+/// \{
+
+void* mi_rezalloc(void* p, size_t newsize);
+void* mi_recalloc(void* p, size_t newcount, size_t size) ;
+
+void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment);
+void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset);
+void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment);
+void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset);
+
+void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize);
+void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size);
+
+void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment);
+void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset);
+void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment);
+void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset);
+
+/// \}
+
+/// \defgroup typed Typed Macros
+///
+/// Typed allocation macros. For example:
+/// ```
+/// int* p = mi_malloc_tp(int)
+/// ```
+///
+/// \{
+
+/// Allocate a block of type \a tp.
+/// @param tp The type of the block to allocate.
+/// @returns A pointer to an object of type \a tp, or
+/// \a NULL if out of memory.
+///
+/// **Example:**
+/// ```
+/// int* p = mi_malloc_tp(int)
+/// ```
+///
+/// @see mi_malloc()
+#define mi_malloc_tp(tp)        ((tp*)mi_malloc(sizeof(tp)))
+
+/// Allocate a zero-initialized block of type \a tp.
+#define mi_zalloc_tp(tp)        ((tp*)mi_zalloc(sizeof(tp)))
+
+/// Allocate \a count zero-initialized blocks of type \a tp.
+#define mi_calloc_tp(tp,count)      ((tp*)mi_calloc(count,sizeof(tp)))
+
+/// Allocate \a count blocks of type \a tp.
+#define mi_mallocn_tp(tp,count)     ((tp*)mi_mallocn(count,sizeof(tp)))
+
+/// Re-allocate to \a count blocks of type \a tp.
+#define mi_reallocn_tp(p,tp,count)  ((tp*)mi_reallocn(p,count,sizeof(tp)))
+
+/// Allocate a block of type \a tp in a heap \a hp.
+#define mi_heap_malloc_tp(hp,tp)        ((tp*)mi_heap_malloc(hp,sizeof(tp)))
+
+/// Allocate a zero-initialized block of type \a tp in a heap \a hp.
+#define mi_heap_zalloc_tp(hp,tp)        ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
+
+/// Allocate \a count zero-initialized blocks of type \a tp in a heap \a hp.
+#define mi_heap_calloc_tp(hp,tp,count)      ((tp*)mi_heap_calloc(hp,count,sizeof(tp)))
+
+/// Allocate \a count blocks of type \a tp in a heap \a hp.
+#define mi_heap_mallocn_tp(hp,tp,count)     ((tp*)mi_heap_mallocn(hp,count,sizeof(tp)))
+
+/// Re-allocate to \a count blocks of type \a tp in a heap \a hp.
+#define mi_heap_reallocn_tp(hp,p,tp,count)  ((tp*)mi_heap_reallocn(p,count,sizeof(tp)))
+
+/// Re-allocate to \a count zero initialized blocks of type \a tp in a heap \a hp.
+#define mi_heap_recalloc_tp(hp,p,tp,count)  ((tp*)mi_heap_recalloc(p,count,sizeof(tp)))
+
+/// \}
+
+/// \defgroup analysis Heap Introspection
+///
+/// Inspect the heap at runtime.
+///
+/// \{
+
+/// Does a heap contain a pointer to a previously allocated block?
+/// @param heap The heap.
+/// @param p Pointer to a previously allocated block (in any heap)-- cannot be some
+///          random pointer!
+/// @returns \a true if the block pointed to by \a p is in the \a heap.
+/// @see mi_heap_check_owned()
+bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
+
+/// Check safely if any pointer is part of a heap.
+/// @param heap The heap.
+/// @param p   Any pointer -- not required to be previously allocated by us.
+/// @returns \a true if \a p points to a block in \a heap.
+///
+/// Note: expensive function, linear in the pages in the heap.
+/// @see mi_heap_contains_block()
+/// @see mi_heap_get_default()
+bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
+
+/// Check safely if any pointer is part of the default heap of this thread.
+/// @param p   Any pointer -- not required to be previously allocated by us.
+/// @returns \a true if \a p points to a block in default heap of this thread.
+///
+/// Note: expensive function, linear in the pages in the heap.
+/// @see mi_heap_contains_block()
+/// @see mi_heap_get_default()
+bool mi_check_owned(const void* p);
+
+/// An area of heap space contains blocks of a single size.
+/// The bytes in freed blocks are `committed - used`.
+typedef struct mi_heap_area_s {
+  void*  blocks;      ///< start of the area containing heap blocks
+  size_t reserved;    ///< bytes reserved for this area
+  size_t committed;   ///< current committed bytes of this area
+  size_t used;        ///< bytes in use by allocated blocks
+  size_t block_size;  ///< size in bytes of one block
+} mi_heap_area_t;
+
+/// Visitor function passed to mi_heap_visit_blocks()
+/// @returns \a true if ok, \a false to stop visiting (i.e. break)
+///
+/// This function is always first called for every \a area
+/// with \a block as a \a NULL pointer. If \a visit_all_blocks
+/// was \a true, the function is then called for every allocated
+/// block in that area.
+typedef bool (mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg);
+
+/// Visit all areas and blocks in a heap.
+/// @param heap The heap to visit.
+/// @param visit_all_blocks If \a true visits all allocated blocks, otherwise
+///                         \a visitor is only called for every heap area.
+/// @param visitor This function is called for every area in the heap
+///                 (with \a block as \a NULL). If \a visit_all_blocks is
+///                 \a true, \a visitor is also called for every allocated
+///                 block in every area (with `block!=NULL`).
+///                 return \a false from this function to stop visiting early.
+/// @param arg Extra argument passed to \a visitor.
+/// @returns \a true if all areas and blocks were visited.
+bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
+
+/// \}
+
+/// \defgroup options Runtime Options
+///
+/// Set runtime behavior.
+///
+/// \{
+
+/// Runtime options.
+typedef enum mi_option_e {
+  // stable options
+  mi_option_show_errors,  ///< Print error messages to `stderr`.
+  mi_option_show_stats,   ///< Print statistics to `stderr` when the program is done.
+  mi_option_verbose,      ///< Print verbose messages to `stderr`.
+
+  // the following options are experimental
+  mi_option_eager_commit, ///< Eagerly commit segments (4MiB) (enabled by default).
+  mi_option_large_os_pages,      ///< Use large OS pages (2MiB in size) if possible
+  mi_option_reserve_huge_os_pages, ///< The number of huge OS pages (1GiB in size) to reserve at the start of the program.
+  mi_option_reserve_huge_os_pages_at, ///< Reserve huge OS pages at node N.
+  mi_option_reserve_os_memory,        ///< Reserve specified amount of OS memory at startup, e.g. "1g" or "512m".
+  mi_option_segment_cache,   ///< The number of segments per thread to keep cached (0).
+  mi_option_page_reset,      ///< Reset page memory after \a mi_option_reset_delay milliseconds when it becomes free.
+  mi_option_abandoned_page_reset, //< Reset free page memory when a thread terminates.
+  mi_option_use_numa_nodes,  ///< Pretend there are at most N NUMA nodes; Use 0 to use the actual detected NUMA nodes at runtime.
+  mi_option_eager_commit_delay,  ///< the first N segments per thread are not eagerly committed (=1). 
+  mi_option_os_tag,          ///< OS tag to assign to mimalloc'd memory
+  mi_option_limit_os_alloc,  ///< If set to 1, do not use OS memory for allocation (but only pre-reserved arenas)
+
+  // v1.x specific options
+  mi_option_eager_region_commit, ///< Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)
+  mi_option_segment_reset,   ///< Experimental
+  mi_option_reset_delay,     ///< Delay in milli-seconds before resetting a page (100ms by default)
+  mi_option_reset_decommits, ///< Experimental
+
+  // v2.x specific options
+  mi_option_allow_decommit,  ///< Enable decommitting memory (=on)
+  mi_option_decommit_delay,  ///< Decommit page memory after N milli-seconds delay (25ms).
+  mi_option_segment_decommit_delay, ///< Decommit large segment memory after N milli-seconds delay (500ms).
+
+  _mi_option_last
+} mi_option_t;
+
+
+bool  mi_option_is_enabled(mi_option_t option);
+void  mi_option_enable(mi_option_t option);
+void  mi_option_disable(mi_option_t option);
+void  mi_option_set_enabled(mi_option_t option, bool enable);
+void  mi_option_set_enabled_default(mi_option_t option, bool enable);
+
+long  mi_option_get(mi_option_t option);
+void  mi_option_set(mi_option_t option, long value);
+void  mi_option_set_default(mi_option_t option, long value);
+
+
+/// \}
+
+/// \defgroup posix Posix
+///
+///  `mi_` prefixed implementations of various Posix, Unix, and C++ allocation functions.
+///  Defined for convenience as all redirect to the regular mimalloc API.
+///
+/// \{
+
+void*  mi_recalloc(void* p, size_t count, size_t size);
+size_t mi_malloc_size(const void* p);
+size_t mi_malloc_usable_size(const void *p);
+
+/// Just as `free` but also checks if the pointer `p` belongs to our heap.
+void   mi_cfree(void* p);
+
+int mi_posix_memalign(void** p, size_t alignment, size_t size);
+int mi__posix_memalign(void** p, size_t alignment, size_t size);
+void* mi_memalign(size_t alignment, size_t size);
+void* mi_valloc(size_t size);
+
+void* mi_pvalloc(size_t size);
+void* mi_aligned_alloc(size_t alignment, size_t size);
+
+/// Correspond s to [reallocarray](https://www.freebsd.org/cgi/man.cgi?query=reallocarray&sektion=3&manpath=freebsd-release-ports)
+/// in FreeBSD.
+void* mi_reallocarray(void* p, size_t count, size_t size);
+
+/// Corresponds to [reallocarr](https://man.netbsd.org/reallocarr.3) in NetBSD.
+int   mi_reallocarr(void* p, size_t count, size_t size);
+
+void mi_free_size(void* p, size_t size);
+void mi_free_size_aligned(void* p, size_t size, size_t alignment);
+void mi_free_aligned(void* p, size_t alignment);
+
+/// \}
+
+/// \defgroup cpp C++ wrappers
+///
+///  `mi_` prefixed implementations of various allocation functions
+///  that use C++ semantics on out-of-memory, generally calling
+///  `std::get_new_handler` and raising a `std::bad_alloc` exception on failure.
+///
+///  Note: use the `mimalloc-new-delete.h` header to override the \a new
+///        and \a delete operators globally. The wrappers here are mostly
+///        for convience for library writers that need to interface with
+///        mimalloc from C++.
+///
+/// \{
+
+/// like mi_malloc(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
+void* mi_new(std::size_t n) noexcept(false);
+
+/// like mi_mallocn(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
+void* mi_new_n(size_t count, size_t size) noexcept(false);
+
+/// like mi_malloc_aligned(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
+void* mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false);
+
+/// like `mi_malloc`, but when out of memory, use `std::get_new_handler` but return \a NULL on failure.
+void* mi_new_nothrow(size_t n);
+
+/// like `mi_malloc_aligned`, but when out of memory, use `std::get_new_handler` but return \a NULL on failure.
+void* mi_new_aligned_nothrow(size_t n, size_t alignment);
+
+/// like mi_realloc(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
+void* mi_new_realloc(void* p, size_t newsize);
+
+/// like mi_reallocn(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
+void* mi_new_reallocn(void* p, size_t newcount, size_t size);
+
+/// \a std::allocator implementation for mimalloc for use in STL containers.
+/// For example:
+/// ```
+/// std::vector<int, mi_stl_allocator<int> > vec;
+/// vec.push_back(1);
+/// vec.pop_back();
+/// ```
+template<class T> struct mi_stl_allocator { }
+
+/// \}
+
+/*! \page build Building
+
+Checkout the sources from Github:
+```
+git clone https://github.com/microsoft/mimalloc
+```
+
+## Windows
+
+Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`).
+The `mimalloc` project builds a static library (in `out/msvc-x64`), while the
+`mimalloc-override` project builds a DLL for overriding malloc
+in the entire program.
+
+## macOS, Linux, BSD, etc.
+
+We use [`cmake`](https://cmake.org)<sup>1</sup> as the build system:
+
+```
+> mkdir -p out/release
+> cd out/release
+> cmake ../..
+> make
+```
+This builds the library as a shared (dynamic)
+library (`.so` or `.dylib`), a static library (`.a`), and
+as a single object file (`.o`).
+
+`> sudo make install` (install the library and header files in `/usr/local/lib`  and `/usr/local/include`)
+
+You can build the debug version which does many internal checks and
+maintains detailed statistics as:
+
+```
+> mkdir -p out/debug
+> cd out/debug
+> cmake -DCMAKE_BUILD_TYPE=Debug ../..
+> make
+```
+This will name the shared library as `libmimalloc-debug.so`.
+
+Finally, you can build a _secure_ version that uses guard pages, encrypted
+free lists, etc, as:
+```
+> mkdir -p out/secure
+> cd out/secure
+> cmake -DMI_SECURE=ON ../..
+> make
+```
+This will name the shared library as `libmimalloc-secure.so`.
+Use `ccmake`<sup>2</sup> instead of `cmake`
+to see and customize all the available build options.
+
+Notes:
+1. Install CMake: `sudo apt-get install cmake`
+2. Install CCMake: `sudo apt-get install cmake-curses-gui`
+
+*/
+
+/*! \page using Using the library
+
+### Build
+
+The preferred usage is including `<mimalloc.h>`, linking with
+the shared- or static library, and using the `mi_malloc` API exclusively for allocation. For example,
+```
+gcc -o myprogram -lmimalloc myfile.c
+```
+
+mimalloc uses only safe OS calls (`mmap` and `VirtualAlloc`) and can co-exist
+with other allocators linked to the same program.
+If you use `cmake`, you can simply use:
+```
+find_package(mimalloc 1.0 REQUIRED)
+```
+in your `CMakeLists.txt` to find a locally installed mimalloc. Then use either:
+```
+target_link_libraries(myapp PUBLIC mimalloc)
+```
+to link with the shared (dynamic) library, or:
+```
+target_link_libraries(myapp PUBLIC mimalloc-static)
+```
+to link with the static library. See `test\CMakeLists.txt` for an example.
+
+### C++
+For best performance in C++ programs, it is also recommended to override the
+global `new` and `delete` operators. For convience, mimalloc provides
+[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project.
+
+In C++, mimalloc also provides the `mi_stl_allocator` struct which implements the `std::allocator`
+interface. For example:
+```
+std::vector<some_struct, mi_stl_allocator<some_struct>> vec;
+vec.push_back(some_struct());
+```
+
+### Statistics
+
+You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`)
+and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version):
+```
+> env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363
+
+175451865205073170563711388363 = 374456281610909315237213 * 468551
+
+heap stats:     peak      total      freed       unit
+normal   2:    16.4 kb    17.5 mb    17.5 mb      16 b   ok
+normal   3:    16.3 kb    15.2 mb    15.2 mb      24 b   ok
+normal   4:      64 b      4.6 kb     4.6 kb      32 b   ok
+normal   5:      80 b    118.4 kb   118.4 kb      40 b   ok
+normal   6:      48 b       48 b       48 b       48 b   ok
+normal  17:     960 b      960 b      960 b      320 b   ok
+
+heap stats:     peak      total      freed       unit
+    normal:    33.9 kb    32.8 mb    32.8 mb       1 b   ok
+      huge:       0 b        0 b        0 b        1 b   ok
+     total:    33.9 kb    32.8 mb    32.8 mb       1 b   ok
+malloc requested:         32.8 mb
+
+ committed:    58.2 kb    58.2 kb    58.2 kb       1 b   ok
+  reserved:     2.0 mb     2.0 mb     2.0 mb       1 b   ok
+     reset:       0 b        0 b        0 b        1 b   ok
+  segments:       1          1          1
+-abandoned:       0
+     pages:       6          6          6
+-abandoned:       0
+     mmaps:       3
+ mmap fast:       0
+ mmap slow:       1
+   threads:       0
+   elapsed:     2.022s
+   process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb
+```
+
+The above model of using the `mi_` prefixed API is not always possible
+though in existing programs that already use the standard malloc interface,
+and another option is to override the standard malloc interface
+completely and redirect all calls to the _mimalloc_ library instead.
+
+See \ref overrides for more info.
+
+*/
+
+/*! \page environment Environment Options
+
+You can set further options either programmatically (using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
+or via environment variables.
+
+- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
+- `MIMALLOC_VERBOSE=1`: show verbose messages.
+- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages.
+- `MIMALLOC_PAGE_RESET=0`: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS
+   that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server)
+   programs. By setting it to `0` no such page resets will be done which can improve performance for programs that are not long
+   running. As an alternative, the `MIMALLOC_DECOMMIT_DELAY=`<msecs> can be set higher (100ms by default) to make the page
+   reset occur less frequently instead of turning it off completely.
+- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages (2MiB) when available; for some workloads this can significantly
+   improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs
+   to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes
+   the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that
+   can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead when possible).
+- `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB _huge_ OS pages. This reserves the huge pages at
+   startup and sometimes this can give a large (latency) performance improvement on big workloads.
+   Usually it is better to not use
+   `MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving
+   contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at
+   startup only once).
+   Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])). With huge OS pages, it may be beneficial to set the setting
+   `MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB)
+   of a thread to not allocate in the huge OS pages; this prevents threads that are short lived
+   and allocate just a little to take up space in the huge OS page area (which cannot be reset).
+- `MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N`: where N is the numa node. This reserves the huge pages at a specific numa node. 
+   (`N` is -1 by default to reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected))
+
+Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
+for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
+OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments.
+
+[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5
+[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017
+
+*/
+
+/*! \page overrides Overriding Malloc
+
+Overriding the standard `malloc` can be done either _dynamically_ or _statically_.
+
+## Dynamic override
+
+This is the recommended way to override the standard malloc interface.
+
+
+### Linux, BSD
+
+On these systems we preload the mimalloc shared
+library so all calls to the standard `malloc` interface are
+resolved to the _mimalloc_ library.
+
+- `env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram`
+
+You can set extra environment variables to check that mimalloc is running,
+like:
+```
+env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram
+```
+or run with the debug version to get detailed statistics:
+```
+env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram
+```
+
+### MacOS
+
+On macOS we can also preload the mimalloc shared
+library so all calls to the standard `malloc` interface are
+resolved to the _mimalloc_ library.
+
+- `env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram`
+
+Note that certain security restrictions may apply when doing this from
+the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash).
+
+(Note: macOS support for dynamic overriding is recent, please report any issues.)
+
+
+### Windows
+
+Overriding on Windows is robust and has the
+particular advantage to be able to redirect all malloc/free calls that go through
+the (dynamic) C runtime allocator, including those from other DLL's or libraries.
+
+The overriding on Windows requires that you link your program explicitly with
+the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
+Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be available
+in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
+The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
+mimalloc (in `mimalloc-override.dll`).
+
+To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some
+call to the mimalloc API in the `main` function, like `mi_version()`
+(or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project
+for an example on how to use this. For best performance on Windows with C++, it
+is also recommended to also override the `new`/`delete` operations (by including
+[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) a single(!) source file in your project).
+
+The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic
+overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected.
+
+(Note: in principle, it is possible to even patch existing executables without any recompilation
+if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll`
+into the import table (and put `mimalloc-redirect.dll` in the same folder)
+Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)).
+
+
+## Static override
+
+On Unix systems, you can also statically link with _mimalloc_ to override the standard
+malloc interface. The recommended way is to link the final program with the
+_mimalloc_ single object file (`mimalloc-override.o`). We use
+an object file instead of a library file as linkers give preference to
+that over archives to resolve symbols. To ensure that the standard
+malloc interface resolves to the _mimalloc_ library, link it as the first
+object file. For example:
+
+```
+gcc -o myprogram mimalloc-override.o  myfile1.c ...
+```
+
+## List of Overrides:
+
+The specific functions that get redirected to the _mimalloc_ library are:
+
+```
+// C
+void*  malloc(size_t size);
+void*  calloc(size_t size, size_t n);
+void*  realloc(void* p, size_t newsize);
+void   free(void* p);
+
+void*  aligned_alloc(size_t alignment, size_t size);
+char*  strdup(const char* s);
+char*  strndup(const char* s, size_t n);
+char*  realpath(const char* fname, char* resolved_name);
+
+
+// C++
+void   operator delete(void* p);
+void   operator delete[](void* p);
+
+void*  operator new(std::size_t n) noexcept(false);
+void*  operator new[](std::size_t n) noexcept(false);
+void*  operator new( std::size_t n, std::align_val_t align) noexcept(false);
+void*  operator new[]( std::size_t n, std::align_val_t align) noexcept(false);
+
+void*  operator new  ( std::size_t count, const std::nothrow_t& tag);
+void*  operator new[]( std::size_t count, const std::nothrow_t& tag);
+void*  operator new  ( std::size_t count, std::align_val_t al, const std::nothrow_t&);
+void*  operator new[]( std::size_t count, std::align_val_t al, const std::nothrow_t&);
+
+// Posix
+int    posix_memalign(void** p, size_t alignment, size_t size);
+
+// Linux
+void*  memalign(size_t alignment, size_t size);
+void*  valloc(size_t size);
+void*  pvalloc(size_t size);
+size_t malloc_usable_size(void *p);
+void*  reallocf(void* p, size_t newsize);
+
+// macOS
+void   vfree(void* p);
+size_t malloc_size(const void* p);
+size_t malloc_good_size(size_t size);
+
+// BSD
+void*  reallocarray( void* p, size_t count, size_t size );
+void*  reallocf(void* p, size_t newsize);
+void   cfree(void* p);
+
+// NetBSD
+int    reallocarr(void* p, size_t count, size_t size);
+
+// Windows
+void*  _expand(void* p, size_t newsize);
+size_t _msize(void* p);
+
+void*  _malloc_dbg(size_t size, int block_type, const char* fname, int line);
+void*  _realloc_dbg(void* p, size_t newsize, int block_type, const char* fname, int line);
+void*  _calloc_dbg(size_t count, size_t size, int block_type, const char* fname, int line);
+void*  _expand_dbg(void* p, size_t size, int block_type, const char* fname, int line);
+size_t _msize_dbg(void* p, int block_type);
+void   _free_dbg(void* p, int block_type);
+```
+
+*/
+
+/*! \page bench Performance
+
+We tested _mimalloc_ against many other top allocators over a wide
+range of benchmarks, ranging from various real world programs to
+synthetic benchmarks that see how the allocator behaves under more
+extreme circumstances.
+
+In our benchmarks, _mimalloc_ always outperforms all other leading
+allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc) (Jan 2021),
+and usually uses less memory (up to 25% more in the worst case).
+A nice property is that it does *consistently* well over the wide
+range of benchmarks.
+
+See the [Performance](https://github.com/microsoft/mimalloc#Performance)
+section in the _mimalloc_ repository for benchmark results,
+or the the technical report for detailed benchmark results.
+
+*/
diff --git a/extlib/mimalloc/doc/mimalloc-doxygen.css b/extlib/mimalloc/doc/mimalloc-doxygen.css
new file mode 100644 (file)
index 0000000..b24f564
--- /dev/null
@@ -0,0 +1,49 @@
+#projectlogo img {
+       padding: 1ex;
+}
+tt, code, kbd, samp, div.memproto, div.fragment, div.line, table.memname {
+       font-family: Consolas, Monaco, Inconsolata, "Courier New", monospace;
+}
+.image img, .textblock img {
+       max-width: 99%;
+       max-height: 350px;
+}
+table.memname, .memname{
+       font-weight: bold;
+}
+code {
+       background-color: #EEE;
+       padding: 0ex 0.25ex;
+}
+body {
+       margin: 1ex 1ex 0ex 1ex;
+       border: 1px solid black;
+}
+.contents table, .contents div, .contents p, .contents dl {
+       font-size: 16px;
+       line-height: 1.44;
+}
+body #nav-tree .label {
+       font-size: 14px;
+}
+a{
+       text-decoration: underline;
+}
+#side-nav {
+       margin-left: 1ex;
+       border-left: 1px solid black;
+}
+#nav-tree {
+       padding-left: 1ex;
+}
+#nav-path {
+       display: none;
+}
+div.fragment {
+       background-color: #EEE;
+       padding: 0.25ex 0.5ex;
+       border-color: black;
+}
+#nav-sync img {
+       display: none;
+}
diff --git a/extlib/mimalloc/doc/mimalloc-logo-100.png b/extlib/mimalloc/doc/mimalloc-logo-100.png
new file mode 100644 (file)
index 0000000..96f0825
Binary files /dev/null and b/extlib/mimalloc/doc/mimalloc-logo-100.png differ
diff --git a/extlib/mimalloc/doc/mimalloc-logo.png b/extlib/mimalloc/doc/mimalloc-logo.png
new file mode 100644 (file)
index 0000000..e0a5a8c
Binary files /dev/null and b/extlib/mimalloc/doc/mimalloc-logo.png differ
diff --git a/extlib/mimalloc/doc/mimalloc-logo.svg b/extlib/mimalloc/doc/mimalloc-logo.svg
new file mode 100644 (file)
index 0000000..672c7e4
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="20mm"
+   height="20mm"
+   viewBox="0 0 10 10"
+   version="1.1"
+   id="svg8"
+   sodipodi:docname="mimalloc-logo.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <defs
+     id="defs2">
+    <linearGradient
+       id="linearGradient6471"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#008da3;stop-opacity:1;"
+         offset="0"
+         id="stop6469" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="23.706667"
+     inkscape:cx="24.864771"
+     inkscape:cy="35.79485"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="3840"
+     inkscape:window-height="2050"
+     inkscape:window-x="-12"
+     inkscape:window-y="-12"
+     inkscape:window-maximized="1"
+     inkscape:snap-object-midpoints="false"
+     inkscape:snap-bbox="false"
+     inkscape:snap-bbox-midpoints="false"
+     inkscape:bbox-nodes="false"
+     inkscape:bbox-paths="false"
+     inkscape:snap-bbox-edge-midpoints="false"
+     showguides="false"
+     showborder="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid815"
+       units="mm"
+       spacingx="0.99999997"
+       spacingy="0.99999997" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-287)">
+    <circle
+       id="path840"
+       cx="5"
+       cy="292"
+       style="fill:#0d8ca4;fill-opacity:0.64444448;fill-rule:nonzero;stroke:#000000;stroke-width:0.56603777;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       r="4.7169809" />
+    <ellipse
+       id="path4522"
+       style="fill:none;stroke:#000000;stroke-width:0.6;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       cx="5.171"
+       cy="292"
+       r="4.8711185" />
+    <g
+       aria-label="malloc"
+       transform="matrix(0.9031136,0,0,0.80782132,0.58122269,37.023319)"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.28599727"
+       id="text6501">
+      <path
+         inkscape:connector-curvature="0"
+         d="m 1.7799307,318.87079 c 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.70159 c 0.013406,-0.0223 0.031281,-0.0469 0.05139,-0.0693 0.017875,-0.0223 0.049156,-0.0447 0.089374,-0.0693 0.040218,-0.0223 0.082671,-0.0358 0.1273581,-0.0358 0.040218,0 0.078202,0.0179 0.1117177,0.0536 0.031281,0.0358 0.049156,0.0827 0.049156,0.143 v 0.67924 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.67924 -0.0223 c 0.0067,-0.0112 0.01564,-0.0223 0.024578,-0.0358 0.00894,-0.0134 0.022344,-0.0268 0.040218,-0.0447 0.017875,-0.0179 0.03575,-0.0335 0.053624,-0.0469 0.017875,-0.0134 0.042453,-0.0246 0.069265,-0.0335 0.026812,-0.009 0.053625,-0.0134 0.080437,-0.0134 0.040218,0 0.078202,0.0179 0.1117177,0.0536 0.031281,0.0358 0.049156,0.0827 0.049156,0.143 v 0.67924 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.67924 c 0,-0.11396 -0.037984,-0.21003 -0.1094833,-0.29047 -0.073734,-0.0804 -0.1631078,-0.12066 -0.2658881,-0.12066 -0.073734,0 -0.1407643,0.0156 -0.1988575,0.0425 -0.058093,0.0268 -0.1094833,0.0626 -0.1541704,0.10725 -0.075968,-0.0983 -0.1720452,-0.14971 -0.290466,-0.14971 -0.1027802,0 -0.1943887,0.029 -0.2748255,0.0849 -0.00894,-0.0179 -0.022343,-0.0335 -0.040218,-0.0469 -0.017875,-0.0134 -0.037984,-0.0201 -0.060328,-0.0201 -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 0.96524 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6515" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 4.2824069,317.69105 c -0.01564,0 -0.029047,0.004 -0.042453,0.009 -0.013406,0.007 -0.026812,0.0156 -0.03575,0.0246 -0.00894,0.0112 -0.017875,0.0223 -0.022344,0.0335 -0.078202,-0.0559 -0.1631079,-0.0849 -0.2569507,-0.0849 -0.145233,0 -0.2658881,0.0626 -0.359731,0.18322 -0.093843,0.12066 -0.1407642,0.26366 -0.1407642,0.42453 0,0.16311 0.046921,0.30611 0.1407642,0.42676 0.093843,0.12066 0.214498,0.18098 0.359731,0.18098 0.093843,0 0.1787483,-0.0268 0.2569507,-0.0849 0.00894,0.0201 0.022344,0.0358 0.040218,0.0491 0.017875,0.0134 0.037984,0.0179 0.060328,0.0179 0.029047,0 0.053625,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.96524 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z m -0.107249,0.77979 c -0.017875,0.0424 -0.040218,0.0782 -0.067031,0.10948 -0.026812,0.0313 -0.055859,0.0559 -0.08714,0.0715 -0.031281,0.0156 -0.064796,0.0224 -0.096077,0.0224 -0.073734,0 -0.1407643,-0.0358 -0.1988575,-0.10949 -0.058093,-0.0737 -0.08714,-0.16757 -0.08714,-0.28376 0,-0.11395 0.029047,-0.2078 0.08714,-0.28153 0.058093,-0.0737 0.1251238,-0.11172 0.1988575,-0.11172 0.049156,0 0.098312,0.0179 0.1429986,0.0536 0.044687,0.0358 0.080437,0.0871 0.107249,0.1497 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6517" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 4.7471525,317.2263 c -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 1.21549 c 0,0.10502 0.0067,0.18545 0.022343,0.24131 0.00447,0.0268 0.017875,0.0469 0.037984,0.0603 0.017875,0.0134 0.040218,0.0201 0.064796,0.0201 0.00894,0 0.017875,0 0.026812,-0.002 0.00447,-0.002 0.011172,-0.004 0.017875,-0.009 0.0067,-0.002 0.013406,-0.004 0.017875,-0.009 0.00447,-0.004 0.011172,-0.009 0.01564,-0.0134 0.00447,-0.004 0.0067,-0.0112 0.011172,-0.0156 0.00447,-0.004 0.0067,-0.0112 0.00894,-0.0179 0.00223,-0.007 0.00447,-0.0134 0.0067,-0.0201 0,-0.007 0.00223,-0.0134 0.00223,-0.0201 v -0.007 c 0,-0.002 -0.00223,-0.004 -0.00223,-0.007 0,-0.002 0,-0.004 0,-0.009 -0.011172,-0.0447 -0.01564,-0.10725 -0.01564,-0.19216 v -1.21549 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6519" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 5.2655226,317.2263 c -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 1.21549 c 0,0.10502 0.0067,0.18545 0.022344,0.24131 0.00447,0.0268 0.017875,0.0469 0.037984,0.0603 0.017875,0.0134 0.040218,0.0201 0.064796,0.0201 0.00894,0 0.017875,0 0.026812,-0.002 0.00447,-0.002 0.011172,-0.004 0.017875,-0.009 0.0067,-0.002 0.013406,-0.004 0.017875,-0.009 0.00447,-0.004 0.011172,-0.009 0.01564,-0.0134 0.00447,-0.004 0.0067,-0.0112 0.011172,-0.0156 0.00447,-0.004 0.0067,-0.0112 0.00894,-0.0179 0.00223,-0.007 0.00447,-0.0134 0.0067,-0.0201 0,-0.007 0.00223,-0.0134 0.00223,-0.0201 v -0.007 c 0,-0.002 -0.00223,-0.004 -0.00223,-0.007 0,-0.002 0,-0.004 0,-0.009 -0.011172,-0.0447 -0.01564,-0.10725 -0.01564,-0.19216 v -1.21549 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6521" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 6.6061344,318.28092 c 0,-0.16087 -0.049156,-0.30387 -0.1429986,-0.42453 -0.093843,-0.12065 -0.2144979,-0.18322 -0.3574966,-0.18322 -0.145233,0 -0.2658881,0.0626 -0.3597309,0.18322 -0.093843,0.12066 -0.1407643,0.26366 -0.1407643,0.42453 0,0.16311 0.046921,0.30611 0.1407643,0.42676 0.093843,0.12066 0.2144979,0.18098 0.3597309,0.18098 0.1429987,0 0.2636538,-0.0603 0.3574966,-0.18098 0.093843,-0.12065 0.1429986,-0.26365 0.1429986,-0.42676 z m -0.2144979,0 c 0,0.11619 -0.031281,0.21003 -0.089374,0.28376 -0.058093,0.0737 -0.1251238,0.10949 -0.1966231,0.10949 -0.073734,0 -0.1407643,-0.0358 -0.1988575,-0.10949 -0.058093,-0.0737 -0.08714,-0.16757 -0.08714,-0.28376 0,-0.11395 0.029047,-0.2078 0.08714,-0.28153 0.058093,-0.0737 0.1251238,-0.11172 0.1988575,-0.11172 0.071499,0 0.1385299,0.038 0.1966231,0.11172 0.058093,0.0737 0.089374,0.16758 0.089374,0.28153 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6523" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 7.6406407,318.47754 c -0.00894,-0.004 -0.01564,-0.007 -0.024578,-0.009 -0.00894,-0.002 -0.017875,-0.004 -0.026812,-0.004 -0.044687,0 -0.075968,0.0201 -0.093843,0.0559 -0.026812,0.0514 -0.060328,0.0894 -0.098312,0.11618 -0.040218,0.0268 -0.080437,0.038 -0.1206551,0.038 -0.071499,0 -0.1340612,-0.0358 -0.1921544,-0.10949 -0.058093,-0.0737 -0.084905,-0.16757 -0.084905,-0.28376 0,-0.11395 0.026812,-0.2078 0.084905,-0.28153 0.058093,-0.0737 0.1206551,-0.11172 0.1921544,-0.11172 0.080437,0 0.1474674,0.0447 0.2055606,0.1296 0.020109,0.0335 0.049156,0.0491 0.089374,0.0491 0.022343,0 0.040218,-0.004 0.058093,-0.0179 0.0067,-0.004 0.013406,-0.009 0.020109,-0.0156 0.0067,-0.007 0.011172,-0.0134 0.01564,-0.0224 0.00447,-0.009 0.0067,-0.0156 0.00894,-0.0246 0.00223,-0.009 0.00447,-0.0179 0.00447,-0.0268 0,-0.004 -0.00223,-0.0112 -0.00223,-0.0156 0,-0.004 -0.00223,-0.009 -0.00223,-0.0134 -0.00223,-0.004 -0.00447,-0.0112 -0.0067,-0.0156 -0.00223,-0.004 -0.00447,-0.009 -0.0067,-0.0134 -0.031281,-0.0447 -0.064796,-0.0827 -0.1027803,-0.11619 -0.037984,-0.0335 -0.080437,-0.0603 -0.1295925,-0.0804 -0.049156,-0.0201 -0.1005459,-0.0313 -0.1519361,-0.0313 -0.1429986,0 -0.2614194,0.0626 -0.3530279,0.18322 -0.093843,0.12066 -0.1385299,0.26366 -0.1385299,0.42453 0,0.16311 0.044687,0.30611 0.1385299,0.42676 0.091608,0.12066 0.2100293,0.18098 0.3530279,0.18098 0.084905,0 0.1631078,-0.0246 0.2346072,-0.0737 0.071499,-0.0492 0.1273581,-0.11172 0.1720452,-0.19215 0.0067,-0.0134 0.011172,-0.0313 0.013406,-0.0514 0,-0.0425 -0.020109,-0.0737 -0.055859,-0.0939 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6525" />
+    </g>
+    <g
+       aria-label="m"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+       id="text848">
+      <path
+         d="m 2.3718985,293.17081 c 0.080862,0 0.1492836,-0.0249 0.211485,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.95313 c 0.037321,-0.0622 0.087082,-0.13062 0.1430634,-0.19282 0.049761,-0.0622 0.1368433,-0.1244 0.2488059,-0.19283 0.1119627,-0.0622 0.2301455,-0.0995 0.3545485,-0.0995 0.1119626,0 0.2177051,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 -0.0622 c 0.018661,-0.0311 0.043541,-0.0622 0.068422,-0.0995 0.024881,-0.0373 0.062201,-0.0746 0.1119626,-0.1244 0.049761,-0.0498 0.099522,-0.0933 0.1492836,-0.13063 0.049761,-0.0373 0.1181828,-0.0684 0.1928246,-0.0933 0.074642,-0.0249 0.1492835,-0.0373 0.2239253,-0.0373 0.1119626,0 0.2177052,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 c 0,-0.31722 -0.1057425,-0.58469 -0.3047872,-0.80861 -0.2052649,-0.22393 -0.4540708,-0.33589 -0.7401976,-0.33589 -0.2052649,0 -0.3918693,0.0435 -0.5535932,0.11818 -0.1617238,0.0746 -0.3047872,0.17416 -0.4291902,0.29857 -0.211485,-0.27369 -0.4789514,-0.41675 -0.8086192,-0.41675 -0.2861268,0 -0.5411529,0.0809 -0.7650782,0.23636 -0.024881,-0.0498 -0.062202,-0.0933 -0.1119627,-0.13062 -0.049761,-0.0373 -0.1057425,-0.056 -0.167944,-0.056 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13062 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.1244029,0.0871 0.211485,0.0871 z"
+         style="stroke-width:0.15923578"
+         id="path834" />
+    </g>
+    <g
+       id="g28"
+       transform="translate(-0.23995531,0.02790178)">
+      <g
+         id="g835">
+        <g
+           transform="matrix(1.0000001,0,0,0.98554676,-7.6075554e-7,4.2369817)"
+           id="g25">
+          <path
+             d="m 7.426334,293.15097 c 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21149 v -2.6871 c 0,-0.0809 -0.031101,-0.14928 -0.087082,-0.21149 -0.062201,-0.056 -0.1306232,-0.0871 -0.2114851,-0.0871 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13063 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.15551 0.087082,0.21149 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 z"
+             style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+             id="path896"
+             inkscape:connector-curvature="0" />
+        </g>
+        <path
+           d="m 7.4249389,289.61754 c 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.086228,-0.1244 0.087082,-0.21149 l 0.0014,-0.14231 c 7.93e-4,-0.0809 -0.031101,-0.14929 -0.087082,-0.21149 -0.062201,-0.056 -0.1306232,-0.0871 -0.2114851,-0.0871 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.086289,0.13062 -0.087082,0.21149 l -0.0014,0.14231 c -8.538e-4,0.0871 0.024881,0.15551 0.087082,0.21149 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 z"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+           id="path898"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="scsscscsscs" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/extlib/mimalloc/doc/spades-logo.png b/extlib/mimalloc/doc/spades-logo.png
new file mode 100644 (file)
index 0000000..d8c73fe
Binary files /dev/null and b/extlib/mimalloc/doc/spades-logo.png differ
diff --git a/extlib/mimalloc/doc/unreal-logo.svg b/extlib/mimalloc/doc/unreal-logo.svg
new file mode 100644 (file)
index 0000000..5d5192a
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   height="706.71118"
+   width="746.71118"
+   viewBox="-150.3282 -273.04775 810.70706 1447.2442"
+   version="1.1"
+   id="svg34"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs24">
+    <clipPath
+       id="a"
+       clipPathUnits="userSpaceOnUse">
+      <path
+         d="M 0,1024 H 1024 V 0 H 0 Z"
+         id="path21" />
+    </clipPath>
+  </defs>
+  <rect
+     style="fill:#b2b2b2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.04786;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     id="rect121"
+     width="1300.7299"
+     height="1264.0651"
+     x="-391.91745"
+     y="-186.69598"
+     rx="154.79872"
+     ry="154.79872" />
+  <path
+     d="m 693.86447,863.90527 v -94.746 h -35.855 v 122.747 h 120.26 v -28 z"
+     id="path26" />
+  <g
+     clip-path="url(#a)"
+     transform="matrix(1.33333,0,0,-1.33333,-408.39652,1133.2393)"
+     id="g32">
+    <path
+       d="m 498.837,117.958 h 20.085 c 0.498,-5.295 -1.063,-7.971 -5.392,-8.386 -4.293,-0.411 -8.612,-0.76 -12.92,-0.77 -17.903,-0.044 -19.822,2.052 -18.737,19.932 0.02,0.333 0.03,0.666 0.063,0.997 0.67,6.667 3.126,9.189 9.81,9.499 5.15,0.238 10.316,0.089 15.476,0.132 5.373,0.044 10.5,-0.337 11.806,-6.626 h 13.198 c 1.86,10.558 -1.6,16.306 -11.74,16.9 -13.059,0.767 -26.228,0.648 -39.293,-0.086 -8.782,-0.493 -13.292,-5.67 -13.804,-14.27 -0.444,-7.454 -0.42,-14.975 -0.007,-22.434 0.441,-7.953 4.16,-11.928 11.938,-13.918 2.87,-0.734 5.785,-1.29 8.68,-1.928 h 26 c 2.091,0.444 4.177,0.913 6.274,1.328 5.615,1.11 11.135,2.918 12.264,9.28 1.114,6.278 1.061,12.763 1.546,19.515 h -35.247 z m -103.4,63.438 v 91.393 h -26.424 v -69.795 l -54.236,70.22 H 273.38 V 181.28 h 26.308 v 68.354 l 1.226,0.31 53.645,-68.547 z m 47.577,45.635 v 26.323 c 12.208,0 24.12,0.002 36.033,-0.003 1.662,0 3.323,-0.048 4.985,-0.059 14.801,-0.1 16.353,-4.42 14.866,-18.979 -0.484,-4.738 -4.073,-7.103 -8.306,-7.175 -15.731,-0.268 -31.469,-0.107 -47.578,-0.107 m 56.443,-33.406 c 0.357,-4.063 0.548,-8.14 0.82,-12.3 h 26.391 c 0,5.758 0.219,11.061 -0.045,16.34 -0.581,11.61 -2.289,16.735 -13.599,18.696 -0.592,0.103 -1.114,0.614 -2.506,1.42 11.369,2.53 15.442,10.208 15.981,20.201 0.267,4.96 0.176,10.017 -0.484,14.932 -1.604,11.95 -5.993,16.673 -17.761,18.885 a 101.743,101.743 0 0 1 -17.843,1.741 c -22.818,0.197 -45.638,0.09 -68.458,0.066 -1.78,-0.002 -3.559,-0.22 -5.646,-0.36 v -91.884 h 26.535 v 25.35 c 6.04,0 11.509,0.111 16.972,-0.025 9.644,-0.24 19.344,-0.086 28.908,-1.129 7.832,-0.854 10.041,-4.046 10.735,-11.933 m 73.129,24.754 h 68.786 v 18.565 h -68.899 v 16.585 h 72.852 v 19.517 h -99.79 v -91.744 h 101.018 v 20.193 h -73.967 z m -319.109,52.037 c 0.004,0.918 -0.563,1.84 -0.847,2.708 h -26.34 c 0,-16.299 0.052,-32.104 -0.036,-47.909 -0.025,-4.314 -0.31,-8.644 -0.772,-12.935 -0.665,-6.161 -4.552,-10.04 -10.412,-10.334 -12.098,-0.61 -24.283,-1.056 -36.347,-0.266 -9.717,0.635 -12.873,4.996 -12.984,14.895 -0.19,16.997 -0.103,33.998 -0.188,50.997 -0.009,1.895 -0.385,3.789 -0.59,5.67 h -26.32 c 0,-22.846 -0.788,-45.02 0.27,-67.106 0.734,-15.35 7.1,-21.4 22.59,-23.992 22.481,-3.765 45.194,-3.61 67.677,-0.266 17.168,2.553 22.995,8.927 23.753,26.069 0.92,20.79 0.464,41.644 0.546,62.47 m 447.926,-53.371 19.515,38.362 19.723,-38.362 z m 2.8,56.306 -49.975,-92.133 h 28.863 l 8.345,15.905 h 59.333 l 8.375,-15.847 h 29.165 l -50.248,92.075 z m -264.917,-161.351 -1.233,-0.292 a 532757.74,532757.74 0 0 1 -30.02,38.7 h -23.4 v -51.93 h 14.433 v 37.887 l 1.47,0.522 30.288,-38.488 h 23.367 v 51.89 h -14.904 z m 187.996,-0.026 -1.193,-0.31 c -9.93,12.813 -19.858,25.627 -29.476,38.039 H 573.309 V 98.583 h 14.777 v 39.2 l 30.889,-39.43 h 23.009 v 51.189 h -14.702 z m -295.244,7.284 h 39.176 v 10.717 H 332.04 v 9.647 h 41.322 V 150.45 H 317.11 V 98.519 h 57.303 v 11.039 h -42.375 z m 338.914,0.018 h 38.455 v 10.44 H 671.1 v 9.635 h 40.57 v 10.3 H 655.83 V 98.556 h 56.742 v 10.952 h -41.62 z M 545.666,98.416 h 14.301 v 51.189 H 545.666 Z M 312.554,585.913 c 0,0 -10.463,51.999 44.874,114.973 55.342,62.972 96.863,85.871 141.707,97.799 l -0.078,-0.046 0.17,0.046 c 0,0 -35.227,-20.517 -35.227,-51.522 0,-9 1.435,-15.184 3.423,-19.315 2.638,-5.488 6.816,-7.354 10.567,-7.372 3.16,-0.018 5.01,1.281 9.01,2.834 V 555.386 c 0,0 0.433,-2.707 2.863,-5.915 3.5,-4.613 9,-10.243 19.335,-10.3 17.629,0.113 39.802,20.026 39.802,20.026 v 135.964 c 0,13.832 -9.9,30.53 -20.39,36.259 0,0 1.43,0.09 3.744,0.089 6.926,0.002 21.784,-0.79 30.063,-7.115 2.3,2.665 39.418,44.665 105.466,57.589 l -0.032,-0.037 0.18,0.037 c 0,0 -36.531,-43.016 -47.981,-64.348 -2.035,-0.121 -2.332,-40.471 -1.993,-80.79 0.329,-38.92 1.253,-77.818 1.789,-80.509 0,0 3.898,-5.794 13.824,-5.844 11.196,-0.057 30.063,7.195 59.643,38.288 l -10e-4,-10e-4 v 10e-4 c 0,0 -0.78,-1.771 -2.35,-4.908 -8.476,-16.938 -39.974,-73.721 -95.924,-106.725 l -0.003,0.003 -0.005,-0.003 -36.29,30.693 -0.927,0.774 -39.58,-41.967 -0.06,0.006 -0.005,-0.006 c 0,0 -90.232,7.633 -127.92,62.015 l 0.179,-0.065 -0.047,0.065 c 0,0 5.707,-2.221 12.148,-2.342 7.547,-0.138 15.472,2.619 15.472,15.229 v 127.85 c 0,6.529 -4.495,13.853 -14.362,13.825 -8.874,-0.023 -21.614,-5.994 -39.01,-23.843 -36.734,-37.685 -51.99,-73.468 -51.99,-73.468 l -0.025,0.136 -0.06,-0.136 M 513,369.156 c 70.386,0 136.56,27.41 186.33,77.18 49.77,49.771 77.18,115.944 77.18,186.33 0,70.386 -27.41,136.559 -77.18,186.33 -49.77,49.77 -115.944,77.18 -186.33,77.18 -70.386,0 -136.56,-27.41 -186.33,-77.18 -49.77,-49.771 -77.18,-115.944 -77.18,-186.33 0,-70.386 27.41,-136.559 77.18,-186.33 49.77,-49.77 115.944,-77.18 186.33,-77.18"
+       id="path28" />
+    <path
+       d="m 513,908.307 c 152.232,0 275.641,-123.409 275.641,-275.64 0,-152.233 -123.409,-275.642 -275.641,-275.642 -152.232,0 -275.641,123.41 -275.641,275.641 0,152.232 123.409,275.641 275.641,275.641 m 0,-559.119 c 75.72,0 146.907,29.487 200.449,83.03 53.542,53.541 83.028,124.728 83.028,200.448 0,75.72 -29.486,146.907 -83.028,200.45 -53.542,53.54 -124.729,83.026 -200.449,83.026 -75.72,0 -146.907,-29.486 -200.449,-83.028 -53.542,-53.542 -83.028,-124.73 -83.028,-200.449 0,-75.72 29.486,-146.907 83.028,-200.449 C 366.093,378.674 437.28,349.188 513,349.188"
+       id="path30" />
+  </g>
+</svg>
diff --git a/extlib/mimalloc/docs/annotated.html b/extlib/mimalloc/docs/annotated.html
new file mode 100644 (file)
index 0000000..f3e392a
--- /dev/null
@@ -0,0 +1,116 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Data Structures</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('annotated.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Data Structures</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here are the data structures with brief descriptions:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="group__analysis.html#structmi__heap__area__t" target="_self">mi_heap_area_t</a></td><td class="desc">An area of heap space contains blocks of a single size </td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="group__cpp.html#structmi__stl__allocator" target="_self">mi_stl_allocator</a></td><td class="desc"><em>std::allocator</em> implementation for mimalloc for use in STL containers </td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/annotated_dup.js b/extlib/mimalloc/docs/annotated_dup.js
new file mode 100644 (file)
index 0000000..6722912
--- /dev/null
@@ -0,0 +1,5 @@
+var annotated_dup =
+[
+    [ "mi_heap_area_t", "group__analysis.html#structmi__heap__area__t", "group__analysis_structmi__heap__area__t" ],
+    [ "mi_stl_allocator", "group__cpp.html#structmi__stl__allocator", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/bc_s.png b/extlib/mimalloc/docs/bc_s.png
new file mode 100644 (file)
index 0000000..e8fb736
Binary files /dev/null and b/extlib/mimalloc/docs/bc_s.png differ
diff --git a/extlib/mimalloc/docs/bdwn.png b/extlib/mimalloc/docs/bdwn.png
new file mode 100644 (file)
index 0000000..bbbba4e
Binary files /dev/null and b/extlib/mimalloc/docs/bdwn.png differ
diff --git a/extlib/mimalloc/docs/bench.html b/extlib/mimalloc/docs/bench.html
new file mode 100644 (file)
index 0000000..6c47289
--- /dev/null
@@ -0,0 +1,114 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Performance</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('bench.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Performance </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>We tested <em>mimalloc</em> against many other top allocators over a wide range of benchmarks, ranging from various real world programs to synthetic benchmarks that see how the allocator behaves under more extreme circumstances.</p>
+<p>In our benchmarks, <em>mimalloc</em> always outperforms all other leading allocators (<em>jemalloc</em>, <em>tcmalloc</em>, <em>Hoard</em>, etc) (Jan 2021), and usually uses less memory (up to 25% more in the worst case). A nice property is that it does <em>consistently</em> well over the wide range of benchmarks.</p>
+<p>See the <a href="https://github.com/microsoft/mimalloc#Performance">Performance</a> section in the <em>mimalloc</em> repository for benchmark results, or the the technical report for detailed benchmark results. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/build.html b/extlib/mimalloc/docs/build.html
new file mode 100644 (file)
index 0000000..dbcc0d7
--- /dev/null
@@ -0,0 +1,137 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Building</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('build.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Building </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Checkout the sources from Github: </p><div class="fragment"><div class="line">git clone https:<span class="comment">//github.com/microsoft/mimalloc</span></div>
+</div><!-- fragment --><h2>Windows</h2>
+<p>Open <code>ide/vs2019/mimalloc.sln</code> in Visual Studio 2019 and build (or <code>ide/vs2017/mimalloc.sln</code>). The <code>mimalloc</code> project builds a static library (in <code>out/msvc-x64</code>), while the <code>mimalloc-override</code> project builds a DLL for overriding malloc in the entire program.</p>
+<h2>macOS, Linux, BSD, etc.</h2>
+<p>We use <a href="https://cmake.org"><code>cmake</code></a><sup>1</sup> as the build system:</p>
+<div class="fragment"><div class="line">&gt; mkdir -p out/release</div>
+<div class="line">&gt; cd out/release</div>
+<div class="line">&gt; cmake ../..</div>
+<div class="line">&gt; make</div>
+</div><!-- fragment --><p> This builds the library as a shared (dynamic) library (<code>.so</code> or <code>.dylib</code>), a static library (<code>.a</code>), and as a single object file (<code>.o</code>).</p>
+<p><code>&gt; sudo make install</code> (install the library and header files in <code>/usr/local/lib</code> and <code>/usr/local/include</code>)</p>
+<p>You can build the debug version which does many internal checks and maintains detailed statistics as:</p>
+<div class="fragment"><div class="line">&gt; mkdir -p out/debug</div>
+<div class="line">&gt; cd out/debug</div>
+<div class="line">&gt; cmake -DCMAKE_BUILD_TYPE=Debug ../..</div>
+<div class="line">&gt; make</div>
+</div><!-- fragment --><p> This will name the shared library as <code>libmimalloc-debug.so</code>.</p>
+<p>Finally, you can build a <em>secure</em> version that uses guard pages, encrypted free lists, etc, as: </p><div class="fragment"><div class="line">&gt; mkdir -p out/secure</div>
+<div class="line">&gt; cd out/secure</div>
+<div class="line">&gt; cmake -DMI_SECURE=ON ../..</div>
+<div class="line">&gt; make</div>
+</div><!-- fragment --><p> This will name the shared library as <code>libmimalloc-secure.so</code>. Use <code>ccmake</code><sup>2</sup> instead of <code>cmake</code> to see and customize all the available build options.</p>
+<p>Notes:</p><ol type="1">
+<li>Install CMake: <code>sudo apt-get install cmake</code></li>
+<li>Install CCMake: <code>sudo apt-get install cmake-curses-gui</code> </li>
+</ol>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/classes.html b/extlib/mimalloc/docs/classes.html
new file mode 100644 (file)
index 0000000..b744c4d
--- /dev/null
@@ -0,0 +1,116 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Data Structure Index</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('classes.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Data Structure Index</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="qindex"><a class="qindex" href="#letter_M">M</a></div>
+<div class="classindex">
+<dl class="classindex even">
+<dt class="alphachar"><a name="letter_M">M</a></dt>
+<dd><a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a></dd><dd><a class="el" href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator</a></dd></dl>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/closed.png b/extlib/mimalloc/docs/closed.png
new file mode 100644 (file)
index 0000000..5e32501
Binary files /dev/null and b/extlib/mimalloc/docs/closed.png differ
diff --git a/extlib/mimalloc/docs/doc.png b/extlib/mimalloc/docs/doc.png
new file mode 100644 (file)
index 0000000..5bfc88d
Binary files /dev/null and b/extlib/mimalloc/docs/doc.png differ
diff --git a/extlib/mimalloc/docs/doxygen.css b/extlib/mimalloc/docs/doxygen.css
new file mode 100644 (file)
index 0000000..f090ef7
--- /dev/null
@@ -0,0 +1,1793 @@
+/* The standard CSS for doxygen 1.9.1 */
+
+body, table, div, p, dl {
+       font: 400 14px/22px Roboto,sans-serif;
+}
+
+p.reference, p.definition {
+       font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+       font-size: 150%;
+}
+
+.title {
+       font: 400 14px/28px Roboto,sans-serif;
+       font-size: 150%;
+       font-weight: bold;
+       margin: 10px 2px;
+}
+
+h2.groupheader {
+       border-bottom: 1px solid #474D4E;
+       color: #0A0B0B;
+       font-size: 150%;
+       font-weight: normal;
+       margin-top: 1.75em;
+       padding-top: 8px;
+       padding-bottom: 4px;
+       width: 100%;
+}
+
+h3.groupheader {
+       font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+       -webkit-transition: text-shadow 0.5s linear;
+       -moz-transition: text-shadow 0.5s linear;
+       -ms-transition: text-shadow 0.5s linear;
+       -o-transition: text-shadow 0.5s linear;
+       transition: text-shadow 0.5s linear;
+       margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+       text-shadow: 0 0 15px cyan;
+}
+
+dt {
+       font-weight: bold;
+}
+
+ul.multicol {
+       -moz-column-gap: 1em;
+       -webkit-column-gap: 1em;
+       column-gap: 1em;
+       -moz-column-count: 3;
+       -webkit-column-count: 3;
+       column-count: 3;
+}
+
+p.startli, p.startdd {
+       margin-top: 2px;
+}
+
+th p.starttd, th p.intertd, th p.endtd {
+        font-size: 100%;
+        font-weight: 700;
+}
+
+p.starttd {
+       margin-top: 0px;
+}
+
+p.endli {
+       margin-bottom: 0px;
+}
+
+p.enddd {
+       margin-bottom: 4px;
+}
+
+p.endtd {
+       margin-bottom: 2px;
+}
+
+p.interli {
+}
+
+p.interdd {
+}
+
+p.intertd {
+}
+
+/* @end */
+
+caption {
+       font-weight: bold;
+}
+
+span.legend {
+       font-size: 70%;
+       text-align: center;
+}
+
+h3.version {
+       font-size: 90%;
+       text-align: center;
+}
+
+div.navtab {
+       border-right: 1px solid #636C6D;
+       padding-right: 15px;
+       text-align: right;
+       line-height: 110%;
+}
+
+div.navtab table {
+       border-spacing: 0;
+}
+
+td.navtab {
+       padding-right: 6px;
+       padding-left: 6px;
+}
+td.navtabHL {
+       background-image: url('tab_a.png');
+       background-repeat:repeat-x;
+       padding-right: 6px;
+       padding-left: 6px;
+}
+
+td.navtabHL a, td.navtabHL a:visited {
+       color: #fff;
+       text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
+}
+
+a.navtab {
+       font-weight: bold;
+}
+
+div.qindex{
+       text-align: center;
+       width: 100%;
+       line-height: 140%;
+       font-size: 130%;
+       color: #A0A0A0;
+}
+
+dt.alphachar{
+       font-size: 180%;
+       font-weight: bold;
+}
+
+.alphachar a{
+       color: black;
+}
+
+.alphachar a:hover, .alphachar a:visited{
+       text-decoration: none;
+}
+
+.classindex dl {
+       padding: 25px;
+       column-count:1
+}
+
+.classindex dd {
+       display:inline-block;
+       margin-left: 50px;
+       width: 90%;
+       line-height: 1.15em;
+}
+
+.classindex dl.odd {
+       background-color: #F0F1F1;
+}
+
+@media(min-width: 1120px) {
+       .classindex dl {
+               column-count:2
+       }
+}
+
+@media(min-width: 1320px) {
+       .classindex dl {
+               column-count:3
+       }
+}
+
+
+/* @group Link Styling */
+
+a {
+       color: #0F1010;
+       font-weight: normal;
+       text-decoration: none;
+}
+
+.contents a:visited {
+       color: #171919;
+}
+
+a:hover {
+       text-decoration: underline;
+}
+
+.contents a.qindexHL:visited {
+        color: #FFFFFF;
+}
+
+a.el {
+       font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+       color: #171919; 
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+       color: #171919; 
+}
+
+/* @end */
+
+dl.el {
+       margin-left: -1cm;
+}
+
+ul {
+  overflow: hidden; /*Fixed: list item bullets overlap floating elements*/
+}
+
+#side-nav ul {
+  overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */
+}
+
+#main-nav ul {
+  overflow: visible; /* reset ul rule for the navigation bar drop down lists */
+}
+
+.fragment {
+  text-align: left;
+  direction: ltr;
+  overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/
+  overflow-y: hidden;
+}
+
+pre.fragment {
+        border: 1px solid #90989A;
+        background-color: #F7F8F8;
+        padding: 4px 6px;
+        margin: 4px 8px 4px 2px;
+        overflow: auto;
+        word-wrap: break-word;
+        font-size:  9pt;
+        line-height: 125%;
+        font-family: monospace, fixed;
+        font-size: 105%;
+}
+
+div.fragment {
+  padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/
+  margin: 4px 8px 4px 2px;
+       background-color: #F7F8F8;
+       border: 1px solid #90989A;
+}
+
+div.line {
+       font-family: monospace, fixed;
+        font-size: 13px;
+       min-height: 13px;
+       line-height: 1.0;
+       text-wrap: unrestricted;
+       white-space: -moz-pre-wrap; /* Moz */
+       white-space: -pre-wrap;     /* Opera 4-6 */
+       white-space: -o-pre-wrap;   /* Opera 7 */
+       white-space: pre-wrap;      /* CSS3  */
+       word-wrap: break-word;      /* IE 5.5+ */
+       text-indent: -53px;
+       padding-left: 53px;
+       padding-bottom: 0px;
+       margin: 0px;
+       -webkit-transition-property: background-color, box-shadow;
+       -webkit-transition-duration: 0.5s;
+       -moz-transition-property: background-color, box-shadow;
+       -moz-transition-duration: 0.5s;
+       -ms-transition-property: background-color, box-shadow;
+       -ms-transition-duration: 0.5s;
+       -o-transition-property: background-color, box-shadow;
+       -o-transition-duration: 0.5s;
+       transition-property: background-color, box-shadow;
+       transition-duration: 0.5s;
+}
+
+div.line:after {
+    content:"\000A";
+    white-space: pre;
+}
+
+div.line.glow {
+       background-color: cyan;
+       box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+       padding-right: 4px;
+       text-align: right;
+       border-right: 2px solid #0F0;
+       background-color: #E8E8E8;
+        white-space: pre;
+}
+span.lineno a {
+       background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+       background-color: #C8C8C8;
+}
+
+.lineno {
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -khtml-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+div.ah, span.ah {
+       background-color: black;
+       font-weight: bold;
+       color: #FFFFFF;
+       margin-bottom: 3px;
+       margin-top: 3px;
+       padding: 0.2em;
+       border: solid thin #333;
+       border-radius: 0.5em;
+       -webkit-border-radius: .5em;
+       -moz-border-radius: .5em;
+       box-shadow: 2px 2px 3px #999;
+       -webkit-box-shadow: 2px 2px 3px #999;
+       -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+       background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+       background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%);
+}
+
+div.classindex ul {
+        list-style: none;
+        padding-left: 0;
+}
+
+div.classindex span.ai {
+        display: inline-block;
+}
+
+div.groupHeader {
+       margin-left: 16px;
+       margin-top: 12px;
+       font-weight: bold;
+}
+
+div.groupText {
+       margin-left: 16px;
+       font-style: italic;
+}
+
+body {
+       background-color: white;
+       color: black;
+        margin: 0;
+}
+
+div.contents {
+       margin-top: 10px;
+       margin-left: 12px;
+       margin-right: 8px;
+}
+
+td.indexkey {
+       background-color: #D6D9D9;
+       font-weight: bold;
+       border: 1px solid #90989A;
+       margin: 2px 0px 2px 0;
+       padding: 2px 10px;
+        white-space: nowrap;
+        vertical-align: top;
+}
+
+td.indexvalue {
+       background-color: #D6D9D9;
+       border: 1px solid #90989A;
+       padding: 2px 10px;
+       margin: 2px 0px;
+}
+
+tr.memlist {
+       background-color: #DADDDE;
+}
+
+p.formulaDsp {
+       text-align: center;
+}
+
+img.formulaDsp {
+       
+}
+
+img.formulaInl, img.inline {
+       vertical-align: middle;
+}
+
+div.center {
+       text-align: center;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        padding: 0px;
+}
+
+div.center img {
+       border: 0px;
+}
+
+address.footer {
+       text-align: right;
+       padding-right: 12px;
+}
+
+img.footer {
+       border: 0px;
+       vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+       color: #008000
+}
+
+span.keywordtype {
+       color: #604020
+}
+
+span.keywordflow {
+       color: #e08000
+}
+
+span.comment {
+       color: #800000
+}
+
+span.preprocessor {
+       color: #806020
+}
+
+span.stringliteral {
+       color: #002080
+}
+
+span.charliteral {
+       color: #008080
+}
+
+span.vhdldigit { 
+       color: #ff00ff 
+}
+
+span.vhdlchar { 
+       color: #000000 
+}
+
+span.vhdlkeyword { 
+       color: #700070 
+}
+
+span.vhdllogic { 
+       color: #ff0000 
+}
+
+blockquote {
+        background-color: #EDEFEF;
+        border-left: 2px solid #5B6364;
+        margin: 0 24px 0 4px;
+        padding: 0 12px 0 16px;
+}
+
+blockquote.DocNodeRTL {
+   border-left: 0;
+   border-right: 2px solid #5B6364;
+   margin: 0 4px 0 24px;
+   padding: 0 16px 0 12px;
+}
+
+/* @end */
+
+/*
+.search {
+       color: #003399;
+       font-weight: bold;
+}
+
+form.search {
+       margin-bottom: 0px;
+       margin-top: 0px;
+}
+
+input.search {
+       font-size: 75%;
+       color: #000080;
+       font-weight: normal;
+       background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+       font-size: 75%;
+}
+
+.dirtab {
+       padding: 4px;
+       border-collapse: collapse;
+       border: 1px solid #636C6D;
+}
+
+th.dirtab {
+       background: #D6D9D9;
+       font-weight: bold;
+}
+
+hr {
+       height: 0px;
+       border: none;
+       border-top: 1px solid #1A1D1D;
+}
+
+hr.footer {
+       height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+       border-spacing: 0px;
+       padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+       -webkit-transition-property: background-color, box-shadow;
+       -webkit-transition-duration: 0.5s;
+       -moz-transition-property: background-color, box-shadow;
+       -moz-transition-duration: 0.5s;
+       -ms-transition-property: background-color, box-shadow;
+       -ms-transition-duration: 0.5s;
+       -o-transition-property: background-color, box-shadow;
+       -o-transition-duration: 0.5s;
+       transition-property: background-color, box-shadow;
+       transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+       background-color: cyan;
+       box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+       background-color: #F2F3F3;
+       border: none;
+       margin: 4px;
+       padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+       padding: 0px 8px 4px 8px;
+       color: #555;
+}
+
+.memSeparator {
+        border-bottom: 1px solid #BBC0C1;
+        line-height: 1px;
+        margin: 0px;
+        padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+        white-space: nowrap;
+}
+
+.memItemRight, .memTemplItemRight {
+       width: 100%;
+}
+
+.memTemplParams {
+       color: #171919;
+        white-space: nowrap;
+       font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtitle {
+       padding: 8px;
+       border-top: 1px solid #697273;
+       border-left: 1px solid #697273;
+       border-right: 1px solid #697273;
+       border-top-right-radius: 4px;
+       border-top-left-radius: 4px;
+       margin-bottom: -1px;
+       background-image: url('nav_f.png');
+       background-repeat: repeat-x;
+       background-color: #C4C8C9;
+       line-height: 1.25;
+       font-weight: 300;
+       float:left;
+}
+
+.permalink
+{
+        font-size: 65%;
+        display: inline-block;
+        vertical-align: middle;
+}
+
+.memtemplate {
+       font-size: 80%;
+       color: #171919;
+       font-weight: normal;
+       margin-left: 9px;
+}
+
+.memnav {
+       background-color: #D6D9D9;
+       border: 1px solid #636C6D;
+       text-align: center;
+       margin: 2px;
+       margin-right: 15px;
+       padding: 2px;
+}
+
+.mempage {
+       width: 100%;
+}
+
+.memitem {
+       padding: 0;
+       margin-bottom: 10px;
+       margin-right: 5px;
+        -webkit-transition: box-shadow 0.5s linear;
+        -moz-transition: box-shadow 0.5s linear;
+        -ms-transition: box-shadow 0.5s linear;
+        -o-transition: box-shadow 0.5s linear;
+        transition: box-shadow 0.5s linear;
+        display: table !important;
+        width: 100%;
+}
+
+.memitem.glow {
+         box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+        font-weight: 400;
+        margin-left: 6px;
+}
+
+.memname td {
+       vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+        border-top: 1px solid #697273;
+        border-left: 1px solid #697273;
+        border-right: 1px solid #697273;
+        padding: 6px 0px 6px 0px;
+        color: #030303;
+        font-weight: bold;
+        text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+        background-color: #BDC2C3;
+        /* opera specific markup */
+        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        border-top-right-radius: 4px;
+        /* firefox specific markup */
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+        -moz-border-radius-topright: 4px;
+        /* webkit specific markup */
+        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        -webkit-border-top-right-radius: 4px;
+
+}
+
+.overload {
+        font-family: "courier new",courier,monospace;
+       font-size: 65%;
+}
+
+.memdoc, dl.reflist dd {
+        border-bottom: 1px solid #697273;      
+        border-left: 1px solid #697273;      
+        border-right: 1px solid #697273; 
+        padding: 6px 10px 2px 10px;
+        background-color: #F7F8F8;
+        border-top-width: 0;
+        background-image:url('nav_g.png');
+        background-repeat:repeat-x;
+        background-color: #FFFFFF;
+        /* opera specific markup */
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        /* firefox specific markup */
+        -moz-border-radius-bottomleft: 4px;
+        -moz-border-radius-bottomright: 4px;
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+        /* webkit specific markup */
+        -webkit-border-bottom-left-radius: 4px;
+        -webkit-border-bottom-right-radius: 4px;
+        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+        padding: 5px;
+}
+
+dl.reflist dd {
+        margin: 0px 0px 10px 0px;
+        padding: 5px;
+}
+
+.paramkey {
+       text-align: right;
+}
+
+.paramtype {
+       white-space: nowrap;
+}
+
+.paramname {
+       color: #602020;
+       white-space: nowrap;
+}
+.paramname em {
+       font-style: normal;
+}
+.paramname code {
+        line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+        margin-left: 0px;
+        padding-left: 0px;
+}       
+
+.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname {
+        font-weight: bold;
+        vertical-align: top;
+}
+        
+.params .paramtype, .tparams .paramtype {
+        font-style: italic;
+        vertical-align: top;
+}       
+        
+.params .paramdir, .tparams .paramdir {
+        font-family: "courier new",courier,monospace;
+        vertical-align: top;
+}
+
+table.mlabels {
+       border-spacing: 0px;
+}
+
+td.mlabels-left {
+       width: 100%;
+       padding: 0px;
+}
+
+td.mlabels-right {
+       vertical-align: bottom;
+       padding: 0px;
+       white-space: nowrap;
+}
+
+span.mlabels {
+        margin-left: 8px;
+}
+
+span.mlabel {
+        background-color: #353A3B;
+        border-top:1px solid #212425;
+        border-left:1px solid #212425;
+        border-right:1px solid #90989A;
+        border-bottom:1px solid #90989A;
+       text-shadow: none;
+       color: white;
+       margin-right: 4px;
+       padding: 2px 3px;
+       border-radius: 3px;
+       font-size: 7pt;
+       white-space: nowrap;
+       vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view inside a (index) page */
+
+div.directory {
+        margin: 10px 0px;
+        border-top: 1px solid #5B6364;
+        border-bottom: 1px solid #5B6364;
+        width: 100%;
+}
+
+.directory table {
+        border-collapse:collapse;
+}
+
+.directory td {
+        margin: 0px;
+        padding: 0px;
+       vertical-align: top;
+}
+
+.directory td.entry {
+        white-space: nowrap;
+        padding-right: 6px;
+       padding-top: 3px;
+}
+
+.directory td.entry a {
+        outline:none;
+}
+
+.directory td.entry a img {
+        border: none;
+}
+
+.directory td.desc {
+        width: 100%;
+        padding-left: 6px;
+       padding-right: 6px;
+       padding-top: 3px;
+       border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+       padding-left: 6px;
+       background-color: #EDEFEF;
+}
+
+.directory img {
+       vertical-align: -30%;
+}
+
+.directory .levels {
+        white-space: nowrap;
+        width: 100%;
+        text-align: right;
+        font-size: 9pt;
+}
+
+.directory .levels span {
+        cursor: pointer;
+        padding-left: 2px;
+        padding-right: 2px;
+       color: #0F1010;
+}
+
+.arrow {
+    color: #5B6364;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    cursor: pointer;
+    font-size: 80%;
+    display: inline-block;
+    width: 16px;
+    height: 22px;
+}
+
+.icon {
+    font-family: Arial, Helvetica;
+    font-weight: bold;
+    font-size: 12px;
+    height: 14px;
+    width: 16px;
+    display: inline-block;
+    background-color: #353A3B;
+    color: white;
+    text-align: center;
+    border-radius: 4px;
+    margin-left: 2px;
+    margin-right: 2px;
+}
+
+.icona {
+    width: 24px;
+    height: 22px;
+    display: inline-block;
+}
+
+.iconfopen {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('folderopen.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+.iconfclosed {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('folderclosed.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+.icondoc {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('doc.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+table.directory {
+    font: 400 14px Roboto,sans-serif;
+}
+
+/* @end */
+
+div.dynheader {
+        margin-top: 8px;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -khtml-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+address {
+       font-style: normal;
+       color: #050505;
+}
+
+table.doxtable caption {
+       caption-side: top;
+}
+
+table.doxtable {
+       border-collapse:collapse;
+        margin-top: 4px;
+        margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+       border: 1px solid #060606;
+       padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+       background-color: #0B0C0C;
+       color: #FFFFFF;
+       font-size: 110%;
+       padding-bottom: 4px;
+       padding-top: 5px;
+}
+
+table.fieldtable {
+        /*width: 100%;*/
+        margin-bottom: 10px;
+        border: 1px solid #697273;
+        border-spacing: 0px;
+        -moz-border-radius: 4px;
+        -webkit-border-radius: 4px;
+        border-radius: 4px;
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+        -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+        box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+        padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+        white-space: nowrap;
+        border-right: 1px solid #697273;
+        border-bottom: 1px solid #697273;
+        vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+        padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+        border-bottom: 1px solid #697273;
+        /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+        margin-top: 0px;
+}       
+        
+.fieldtable td.fielddoc p:last-child {
+        margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+        border-bottom: none;
+}
+
+.fieldtable th {
+        background-image:url('nav_f.png');
+        background-repeat:repeat-x;
+        background-color: #C4C8C9;
+        font-size: 90%;
+        color: #030303;
+        padding-bottom: 4px;
+        padding-top: 5px;
+        text-align:left;
+        font-weight: 400;
+        -moz-border-radius-topleft: 4px;
+        -moz-border-radius-topright: 4px;
+        -webkit-border-top-left-radius: 4px;
+        -webkit-border-top-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        border-bottom: 1px solid #697273;
+}
+
+
+.tabsearch {
+       top: 0px;
+       left: 10px;
+       height: 36px;
+       background-image: url('tab_b.png');
+       z-index: 101;
+       overflow: hidden;
+       font-size: 13px;
+}
+
+.navpath ul
+{
+       font-size: 11px;
+       background-image:url('tab_b.png');
+       background-repeat:repeat-x;
+       background-position: 0 -5px;
+       height:30px;
+       line-height:30px;
+       color:#494F50;
+       border:solid 1px #8C9596;
+       overflow:hidden;
+       margin:0px;
+       padding:0px;
+}
+
+.navpath li
+{
+       list-style-type:none;
+       float:left;
+       padding-left:10px;
+       padding-right:15px;
+       background-image:url('bc_s.png');
+       background-repeat:no-repeat;
+       background-position:right;
+       color:#0A0B0B;
+}
+
+.navpath li.navelem a
+{
+       height:32px;
+       display:block;
+       text-decoration: none;
+       outline: none;
+       color: #040404;
+       font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+       text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+       text-decoration: none;        
+}
+
+.navpath li.navelem a:hover
+{
+       color:#2E3233;
+}
+
+.navpath li.footer
+{
+        list-style-type:none;
+        float:right;
+        padding-left:10px;
+        padding-right:15px;
+        background-image:none;
+        background-repeat:no-repeat;
+        background-position:right;
+        color:#0A0B0B;
+        font-size: 8pt;
+}
+
+
+div.summary
+{
+       float: right;
+       font-size: 8pt;
+       padding-right: 5px;
+       width: 50%;
+       text-align: right;
+}       
+
+div.summary a
+{
+       white-space: nowrap;
+}
+
+table.classindex
+{
+        margin: 10px;
+        white-space: nowrap;
+        margin-left: 3%;
+        margin-right: 3%;
+        width: 94%;
+        border: 0;
+        border-spacing: 0; 
+        padding: 0;
+}
+
+div.ingroups
+{
+       font-size: 8pt;
+       width: 50%;
+       text-align: left;
+}
+
+div.ingroups a
+{
+       white-space: nowrap;
+}
+
+div.header
+{
+        background-image:url('nav_h.png');
+        background-repeat:repeat-x;
+       background-color: #F2F3F3;
+       margin:  0px;
+       border-bottom: 1px solid #90989A;
+}
+
+div.headertitle
+{
+       padding: 5px 5px 5px 10px;
+}
+
+.PageDocRTL-title div.headertitle {
+  text-align: right;
+  direction: rtl;
+}
+
+dl {
+        padding: 0 0 0 0;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */
+dl.section {
+       margin-left: 0px;
+       padding-left: 0px;
+}
+
+dl.section.DocNodeRTL {
+  margin-right: 0px;
+  padding-right: 0px;
+}
+
+dl.note {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #D0C000;
+}
+
+dl.note.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #D0C000;
+}
+
+dl.warning, dl.attention {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #FF0000;
+}
+
+dl.warning.DocNodeRTL, dl.attention.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #00D000;
+}
+
+dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #00D000;
+}
+
+dl.deprecated {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #505050;
+}
+
+dl.deprecated.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #505050;
+}
+
+dl.todo {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #00C0E0;
+}
+
+dl.todo.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #00C0E0;
+}
+
+dl.test {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #3030E0;
+}
+
+dl.test.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #3030E0;
+}
+
+dl.bug {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #C08050;
+}
+
+dl.bug.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #C08050;
+}
+
+dl.section dd {
+       margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+       text-align: center;
+       vertical-align: bottom;
+       border-collapse: separate;
+}
+#projectlogo img
+{ 
+       border: 0px none;
+}
+#projectalign
+{
+        vertical-align: middle;
+}
+
+#projectname
+{
+       font: 300% Tahoma, Arial,sans-serif;
+       margin: 0px;
+       padding: 2px 0px;
+}
+    
+#projectbrief
+{
+       font: 120% Tahoma, Arial,sans-serif;
+       margin: 0px;
+       padding: 0px;
+}
+
+#projectnumber
+{
+       font: 50% Tahoma, Arial,sans-serif;
+       margin: 0px;
+       padding: 0px;
+}
+
+#titlearea
+{
+       padding: 0px;
+       margin: 0px;
+       width: 100%;
+       border-bottom: 1px solid #212425;
+}
+
+.image
+{
+        text-align: center;
+}
+
+.dotgraph
+{
+        text-align: center;
+}
+
+.mscgraph
+{
+        text-align: center;
+}
+
+.plantumlgraph
+{
+        text-align: center;
+}
+
+.diagraph
+{
+        text-align: center;
+}
+
+.caption
+{
+       font-weight: bold;
+}
+
+div.zoom
+{
+       border: 1px solid #4F5657;
+}
+
+dl.citelist {
+        margin-bottom:50px;
+}
+
+dl.citelist dt {
+        color:#080909;
+        float:left;
+        font-weight:bold;
+        margin-right:10px;
+        padding:5px;
+        text-align:right;
+        width:52px;
+}
+
+dl.citelist dd {
+        margin:2px 0 2px 72px;
+        padding:5px 0;
+}
+
+div.toc {
+        padding: 14px 25px;
+        background-color: #E8EAEA;
+        border: 1px solid #B1B7B8;
+        border-radius: 7px 7px 7px 7px;
+        float: right;
+        height: auto;
+        margin: 0 8px 10px 10px;
+        width: 200px;
+}
+
+.PageDocRTL-title div.toc {
+  float: left !important;
+  text-align: right;
+}
+
+div.toc li {
+        background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+        font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+        margin-top: 5px;
+        padding-left: 10px;
+        padding-top: 2px;
+}
+
+.PageDocRTL-title div.toc li {
+  background-position-x: right !important;
+  padding-left: 0 !important;
+  padding-right: 10px;
+}
+
+div.toc h3 {
+        font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+       color: #171919;
+        border-bottom: 0 none;
+        margin: 0;
+}
+
+div.toc ul {
+        list-style: none outside none;
+        border: medium none;
+        padding: 0px;
+}       
+
+div.toc li.level1 {
+        margin-left: 0px;
+}
+
+div.toc li.level2 {
+        margin-left: 15px;
+}
+
+div.toc li.level3 {
+        margin-left: 30px;
+}
+
+div.toc li.level4 {
+        margin-left: 45px;
+}
+
+span.emoji {
+        /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html
+         * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;
+         */
+}
+
+.PageDocRTL-title div.toc li.level1 {
+  margin-left: 0 !important;
+  margin-right: 0;
+}
+
+.PageDocRTL-title div.toc li.level2 {
+  margin-left: 0 !important;
+  margin-right: 15px;
+}
+
+.PageDocRTL-title div.toc li.level3 {
+  margin-left: 0 !important;
+  margin-right: 30px;
+}
+
+.PageDocRTL-title div.toc li.level4 {
+  margin-left: 0 !important;
+  margin-right: 45px;
+}
+
+.inherit_header {
+        font-weight: bold;
+        color: gray;
+        cursor: pointer;
+       -webkit-touch-callout: none;
+       -webkit-user-select: none;
+       -khtml-user-select: none;
+       -moz-user-select: none;
+       -ms-user-select: none;
+       user-select: none;
+}
+
+.inherit_header td {
+        padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+        display: none;
+}
+
+tr.heading h2 {
+        margin-top: 12px;
+        margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+        position: absolute;
+        display: none;
+}
+
+#powerTip {
+       cursor: default;
+       white-space: nowrap;
+       background-color: white;
+       border: 1px solid gray;
+       border-radius: 4px 4px 4px 4px;
+       box-shadow: 1px 1px 7px gray;
+       display: none;
+       font-size: smaller;
+       max-width: 80%;
+       opacity: 0.9;
+       padding: 1ex 1em 1em;
+       position: absolute;
+       z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+        color: grey;
+       font-style: italic;
+}
+
+#powerTip div.ttname a {
+        font-weight: bold;
+}
+
+#powerTip div.ttname {
+        font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+        color: #006318;
+}
+
+#powerTip div {
+        margin: 0px;
+        padding: 0px;
+        font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+       content: "";
+       position: absolute;
+       margin: 0px;
+}
+
+#powerTip.n:after,  #powerTip.n:before,
+#powerTip.s:after,  #powerTip.s:before,
+#powerTip.w:after,  #powerTip.w:before,
+#powerTip.e:after,  #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+       border: solid transparent;
+       content: " ";
+       height: 0;
+       width: 0;
+       position: absolute;
+}
+
+#powerTip.n:after,  #powerTip.s:after,
+#powerTip.w:after,  #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+       border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before,  #powerTip.s:before,
+#powerTip.w:before,  #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+       border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after,  #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+       top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+       border-top-color: #FFFFFF;
+       border-width: 10px;
+       margin: 0px -10px;
+}
+#powerTip.n:before {
+       border-top-color: #808080;
+       border-width: 11px;
+       margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+       left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+       right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+       left: 14px;
+}
+
+#powerTip.s:after,  #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+       bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+       border-bottom-color: #FFFFFF;
+       border-width: 10px;
+       margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+       border-bottom-color: #808080;
+       border-width: 11px;
+       margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+       left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+       right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+       left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+       left: 100%;
+}
+#powerTip.e:after {
+       border-left-color: #FFFFFF;
+       border-width: 10px;
+       top: 50%;
+       margin-top: -10px;
+}
+#powerTip.e:before {
+       border-left-color: #808080;
+       border-width: 11px;
+       top: 50%;
+       margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+       right: 100%;
+}
+#powerTip.w:after {
+       border-right-color: #FFFFFF;
+       border-width: 10px;
+       top: 50%;
+       margin-top: -10px;
+}
+#powerTip.w:before {
+       border-right-color: #808080;
+       border-width: 11px;
+       top: 50%;
+       margin-top: -11px;
+}
+
+@media print
+{
+  #top { display: none; }
+  #side-nav { display: none; }
+  #nav-path { display: none; }
+  body { overflow:visible; }
+  h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+  .summary { display: none; }
+  .memitem { page-break-inside: avoid; }
+  #doc-content
+  {
+    margin-left:0 !important;
+    height:auto !important;
+    width:auto !important;
+    overflow:inherit;
+    display:inline;
+  }
+}
+
+/* @group Markdown */
+
+table.markdownTable {
+       border-collapse:collapse;
+        margin-top: 4px;
+        margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+       border: 1px solid #060606;
+       padding: 3px 7px 2px;
+}
+
+table.markdownTable tr {
+}
+
+th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {
+       background-color: #0B0C0C;
+       color: #FFFFFF;
+       font-size: 110%;
+       padding-bottom: 4px;
+       padding-top: 5px;
+}
+
+th.markdownTableHeadLeft, td.markdownTableBodyLeft {
+       text-align: left
+}
+
+th.markdownTableHeadRight, td.markdownTableBodyRight {
+       text-align: right
+}
+
+th.markdownTableHeadCenter, td.markdownTableBodyCenter {
+       text-align: center
+}
+
+.DocNodeRTL {
+  text-align: right;
+  direction: rtl;
+}
+
+.DocNodeLTR {
+  text-align: left;
+  direction: ltr;
+}
+
+table.DocNodeRTL {
+   width: auto;
+   margin-right: 0;
+   margin-left: auto;
+}
+
+table.DocNodeLTR {
+   width: auto;
+   margin-right: auto;
+   margin-left: 0;
+}
+
+tt, code, kbd, samp
+{
+  display: inline-block;
+  direction:ltr; 
+}
+/* @end */
+
+u {
+       text-decoration: underline;
+}
+
diff --git a/extlib/mimalloc/docs/doxygen.png b/extlib/mimalloc/docs/doxygen.png
new file mode 100644 (file)
index 0000000..c0249e9
Binary files /dev/null and b/extlib/mimalloc/docs/doxygen.png differ
diff --git a/extlib/mimalloc/docs/dynsections.js b/extlib/mimalloc/docs/dynsections.js
new file mode 100644 (file)
index 0000000..3174bd7
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ @licstart  The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend  The above is the entire license notice for the JavaScript code in this file
+ */
+function toggleVisibility(linkObj)
+{
+ var base = $(linkObj).attr('id');
+ var summary = $('#'+base+'-summary');
+ var content = $('#'+base+'-content');
+ var trigger = $('#'+base+'-trigger');
+ var src=$(trigger).attr('src');
+ if (content.is(':visible')===true) {
+   content.hide();
+   summary.show();
+   $(linkObj).addClass('closed').removeClass('opened');
+   $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+   content.show();
+   summary.hide();
+   $(linkObj).removeClass('closed').addClass('opened');
+   $(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+ return false;
+}
+
+function updateStripes()
+{
+  $('table.directory tr').
+       removeClass('even').filter(':visible:even').addClass('even');
+}
+
+function toggleLevel(level)
+{
+  $('table.directory tr').each(function() {
+    var l = this.id.split('_').length-1;
+    var i = $('#img'+this.id.substring(3));
+    var a = $('#arr'+this.id.substring(3));
+    if (l<level+1) {
+      i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
+      a.html('&#9660;');
+      $(this).show();
+    } else if (l==level+1) {
+      i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
+      a.html('&#9658;');
+      $(this).show();
+    } else {
+      $(this).hide();
+    }
+  });
+  updateStripes();
+}
+
+function toggleFolder(id)
+{
+  // the clicked row
+  var currentRow = $('#row_'+id);
+
+  // all rows after the clicked row
+  var rows = currentRow.nextAll("tr");
+
+  var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
+
+  // only match elements AFTER this one (can't hide elements before)
+  var childRows = rows.filter(function() { return this.id.match(re); });
+
+  // first row is visible we are HIDING
+  if (childRows.filter(':first').is(':visible')===true) {
+    // replace down arrow by right arrow for current row
+    var currentRowSpans = currentRow.find("span");
+    currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+    currentRowSpans.filter(".arrow").html('&#9658;');
+    rows.filter("[id^=row_"+id+"]").hide(); // hide all children
+  } else { // we are SHOWING
+    // replace right arrow by down arrow for current row
+    var currentRowSpans = currentRow.find("span");
+    currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
+    currentRowSpans.filter(".arrow").html('&#9660;');
+    // replace down arrows by right arrows for child rows
+    var childRowsSpans = childRows.find("span");
+    childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+    childRowsSpans.filter(".arrow").html('&#9658;');
+    childRows.show(); //show all children
+  }
+  updateStripes();
+}
+
+
+function toggleInherit(id)
+{
+  var rows = $('tr.inherit.'+id);
+  var img = $('tr.inherit_header.'+id+' img');
+  var src = $(img).attr('src');
+  if (rows.filter(':first').is(':visible')===true) {
+    rows.css('display','none');
+    $(img).attr('src',src.substring(0,src.length-8)+'closed.png');
+  } else {
+    rows.css('display','table-row'); // using show() causes jump in firefox
+    $(img).attr('src',src.substring(0,src.length-10)+'open.png');
+  }
+}
+/* @license-end */
diff --git a/extlib/mimalloc/docs/environment.html b/extlib/mimalloc/docs/environment.html
new file mode 100644 (file)
index 0000000..f571f95
--- /dev/null
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Environment Options</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('environment.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Environment Options </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>You can set further options either programmatically (using <a href="https://microsoft.github.io/mimalloc/group__options.html"><code>mi_option_set</code></a>), or via environment variables.</p>
+<ul>
+<li><code>MIMALLOC_SHOW_STATS=1</code>: show statistics when the program terminates.</li>
+<li><code>MIMALLOC_VERBOSE=1</code>: show verbose messages.</li>
+<li><code>MIMALLOC_SHOW_ERRORS=1</code>: show error and warning messages.</li>
+<li><code>MIMALLOC_PAGE_RESET=0</code>: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server) programs. By setting it to <code>0</code> no such page resets will be done which can improve performance for programs that are not long running. As an alternative, the <code>MIMALLOC_RESET_DELAY=</code>&lt;msecs&gt; can be set higher (100ms by default) to make the page reset occur less frequently instead of turning it off completely.</li>
+<li><code>MIMALLOC_LARGE_OS_PAGES=1</code>: use large OS pages (2MiB) when available; for some workloads this can significantly improve performance. Use <code>MIMALLOC_VERBOSE</code> to check if the large OS pages are enabled &ndash; usually one needs to explicitly allow large OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>). However, sometimes the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that can have fragmented memory (for that reason, we generally recommend to use <code>MIMALLOC_RESERVE_HUGE_OS_PAGES</code> instead when possible).</li>
+<li><code>MIMALLOC_RESERVE_HUGE_OS_PAGES=N</code>: where N is the number of 1GiB <em>huge</em> OS pages. This reserves the huge pages at startup and sometimes this can give a large (latency) performance improvement on big workloads. Usually it is better to not use <code>MIMALLOC_LARGE_OS_PAGES</code> in combination with this setting. Just like large OS pages, use with care as reserving contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at startup only once). Note that we usually need to explicitly enable huge OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>)). With huge OS pages, it may be beneficial to set the setting <code>MIMALLOC_EAGER_COMMIT_DELAY=N</code> (<code>N</code> is 1 by default) to delay the initial <code>N</code> segments (of 4MiB) of a thread to not allocate in the huge OS pages; this prevents threads that are short lived and allocate just a little to take up space in the huge OS page area (which cannot be reset).</li>
+<li><code>MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N</code>: where N is the numa node. This reserves the huge pages at a specific numa node. (<code>N</code> is -1 by default to reserve huge pages evenly among the given number of numa nodes (or use the available ones as detected))</li>
+</ul>
+<p>Use caution when using <code>fork</code> in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write for all pages in the original process including the huge OS pages. When any memory is now written in that area, the OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/folderclosed.png b/extlib/mimalloc/docs/folderclosed.png
new file mode 100644 (file)
index 0000000..53b7aa6
Binary files /dev/null and b/extlib/mimalloc/docs/folderclosed.png differ
diff --git a/extlib/mimalloc/docs/folderopen.png b/extlib/mimalloc/docs/folderopen.png
new file mode 100644 (file)
index 0000000..92225ee
Binary files /dev/null and b/extlib/mimalloc/docs/folderopen.png differ
diff --git a/extlib/mimalloc/docs/functions.html b/extlib/mimalloc/docs/functions.html
new file mode 100644 (file)
index 0000000..373fafe
--- /dev/null
@@ -0,0 +1,123 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Data Fields</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('functions.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all struct and union fields with links to the structures/unions they belong to:</div><ul>
+<li>block_size
+: <a class="el" href="group__analysis.html#a332a6c14d736a99699d5453a1cb04b41">mi_heap_area_t</a>
+</li>
+<li>blocks
+: <a class="el" href="group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8">mi_heap_area_t</a>
+</li>
+<li>committed
+: <a class="el" href="group__analysis.html#ab47526df656d8837ec3e97f11b83f835">mi_heap_area_t</a>
+</li>
+<li>reserved
+: <a class="el" href="group__analysis.html#ae848a3e6840414891035423948ca0383">mi_heap_area_t</a>
+</li>
+<li>used
+: <a class="el" href="group__analysis.html#ab820302c5cd0df133eb8e51650a008b4">mi_heap_area_t</a>
+</li>
+</ul>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/functions_vars.html b/extlib/mimalloc/docs/functions_vars.html
new file mode 100644 (file)
index 0000000..a12ef62
--- /dev/null
@@ -0,0 +1,123 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Data Fields - Variables</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('functions_vars.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>block_size
+: <a class="el" href="group__analysis.html#a332a6c14d736a99699d5453a1cb04b41">mi_heap_area_t</a>
+</li>
+<li>blocks
+: <a class="el" href="group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8">mi_heap_area_t</a>
+</li>
+<li>committed
+: <a class="el" href="group__analysis.html#ab47526df656d8837ec3e97f11b83f835">mi_heap_area_t</a>
+</li>
+<li>reserved
+: <a class="el" href="group__analysis.html#ae848a3e6840414891035423948ca0383">mi_heap_area_t</a>
+</li>
+<li>used
+: <a class="el" href="group__analysis.html#ab820302c5cd0df133eb8e51650a008b4">mi_heap_area_t</a>
+</li>
+</ul>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__aligned.html b/extlib/mimalloc/docs/group__aligned.html
new file mode 100644 (file)
index 0000000..bd11f30
--- /dev/null
@@ -0,0 +1,465 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Aligned Allocation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__aligned.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#define-members">Macros</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Aligned Allocation</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Allocating aligned memory blocks.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga83c03016066b438f51a8095e9140be06"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga83c03016066b438f51a8095e9140be06">MI_ALIGNMENT_MAX</a></td></tr>
+<tr class="memdesc:ga83c03016066b438f51a8095e9140be06"><td class="mdescLeft">&#160;</td><td class="mdescRight">The maximum supported alignment size (currently 1MiB).  <a href="group__aligned.html#ga83c03016066b438f51a8095e9140be06">More...</a><br /></td></tr>
+<tr class="separator:ga83c03016066b438f51a8095e9140be06"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga68930196751fa2cca9e1fd0d71bade56"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56">mi_malloc_aligned</a> (size_t size, size_t alignment)</td></tr>
+<tr class="memdesc:ga68930196751fa2cca9e1fd0d71bade56"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>size</em> bytes aligned by <em>alignment</em>.  <a href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56">More...</a><br /></td></tr>
+<tr class="separator:ga68930196751fa2cca9e1fd0d71bade56"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga0cadbcf5b89a7b6fb171bc8df8734819"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819">mi_zalloc_aligned</a> (size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga0cadbcf5b89a7b6fb171bc8df8734819"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga53dddb4724042a90315b94bc268fb4c9"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9">mi_calloc_aligned</a> (size_t count, size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga53dddb4724042a90315b94bc268fb4c9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4028d1cf4aa4c87c880747044a8322ae"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae">mi_realloc_aligned</a> (void *p, size_t newsize, size_t alignment)</td></tr>
+<tr class="separator:ga4028d1cf4aa4c87c880747044a8322ae"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga5850da130c936bd77db039dcfbc8295d"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga5850da130c936bd77db039dcfbc8295d">mi_malloc_aligned_at</a> (size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="memdesc:ga5850da130c936bd77db039dcfbc8295d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>size</em> bytes aligned by <em>alignment</em> at a specified <em>offset</em>.  <a href="group__aligned.html#ga5850da130c936bd77db039dcfbc8295d">More...</a><br /></td></tr>
+<tr class="separator:ga5850da130c936bd77db039dcfbc8295d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga5f8c2353766db522565e642fafd8a3f8"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8">mi_zalloc_aligned_at</a> (size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga5f8c2353766db522565e642fafd8a3f8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga08647c4593f3b2eef24a919a73eba3a3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3">mi_calloc_aligned_at</a> (size_t count, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga08647c4593f3b2eef24a919a73eba3a3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf66a9ae6c6f08bd6be6fb6ea771faffb"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb">mi_realloc_aligned_at</a> (void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:gaf66a9ae6c6f08bd6be6fb6ea771faffb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>Allocating aligned memory blocks. </p>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga83c03016066b438f51a8095e9140be06"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga83c03016066b438f51a8095e9140be06">&#9670;&nbsp;</a></span>MI_ALIGNMENT_MAX</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define MI_ALIGNMENT_MAX</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>The maximum supported alignment size (currently 1MiB). </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga53dddb4724042a90315b94bc268fb4c9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga53dddb4724042a90315b94bc268fb4c9">&#9670;&nbsp;</a></span>mi_calloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_calloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga08647c4593f3b2eef24a919a73eba3a3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga08647c4593f3b2eef24a919a73eba3a3">&#9670;&nbsp;</a></span>mi_calloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_calloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga68930196751fa2cca9e1fd0d71bade56"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga68930196751fa2cca9e1fd0d71bade56">&#9670;&nbsp;</a></span>mi_malloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_malloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>size</em> bytes aligned by <em>alignment</em>. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>number of bytes to allocate. </td></tr>
+    <tr><td class="paramname">alignment</td><td>the minimal alignment of the allocated memory. Must be less than <a class="el" href="group__aligned.html#ga83c03016066b438f51a8095e9140be06" title="The maximum supported alignment size (currently 1MiB).">MI_ALIGNMENT_MAX</a>. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the allocated memory or <em>NULL</em> if out of memory. The returned pointer is aligned by <em>alignment</em>, i.e. <code>(uintptr_t)p % alignment == 0</code>.</dd></dl>
+<p>Returns a unique pointer if called with <em>size</em> 0. </p><dl class="section see"><dt>See also</dt><dd><a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=vs-2017">_aligned_malloc</a> (on Windows) </dd>
+<dd>
+<a href="http://man.openbsd.org/reallocarray">aligned_alloc</a> (on BSD, with switched arguments!) </dd>
+<dd>
+<a href="https://linux.die.net/man/3/posix_memalign">posix_memalign</a> (on Posix, with switched arguments!) </dd>
+<dd>
+<a href="https://linux.die.net/man/3/posix_memalign">memalign</a> (on Linux, with switched arguments!) </dd></dl>
+
+</div>
+</div>
+<a id="ga5850da130c936bd77db039dcfbc8295d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5850da130c936bd77db039dcfbc8295d">&#9670;&nbsp;</a></span>mi_malloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_malloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>size</em> bytes aligned by <em>alignment</em> at a specified <em>offset</em>. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>number of bytes to allocate. </td></tr>
+    <tr><td class="paramname">alignment</td><td>the minimal alignment of the allocated memory at <em>offset</em>. </td></tr>
+    <tr><td class="paramname">offset</td><td>the offset that should be aligned. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the allocated memory or <em>NULL</em> if out of memory. The returned pointer is aligned by <em>alignment</em> at <em>offset</em>, i.e. <code>((uintptr_t)p + offset) % alignment == 0</code>.</dd></dl>
+<p>Returns a unique pointer if called with <em>size</em> 0. </p><dl class="section see"><dt>See also</dt><dd><a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-offset-malloc?view=vs-2017">_aligned_offset_malloc</a> (on Windows) </dd></dl>
+
+</div>
+</div>
+<a id="ga4028d1cf4aa4c87c880747044a8322ae"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4028d1cf4aa4c87c880747044a8322ae">&#9670;&nbsp;</a></span>mi_realloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_realloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaf66a9ae6c6f08bd6be6fb6ea771faffb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf66a9ae6c6f08bd6be6fb6ea771faffb">&#9670;&nbsp;</a></span>mi_realloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_realloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga0cadbcf5b89a7b6fb171bc8df8734819"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0cadbcf5b89a7b6fb171bc8df8734819">&#9670;&nbsp;</a></span>mi_zalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_zalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga5f8c2353766db522565e642fafd8a3f8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5f8c2353766db522565e642fafd8a3f8">&#9670;&nbsp;</a></span>mi_zalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_zalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__aligned.js b/extlib/mimalloc/docs/group__aligned.js
new file mode 100644 (file)
index 0000000..06ccb0c
--- /dev/null
@@ -0,0 +1,12 @@
+var group__aligned =
+[
+    [ "MI_ALIGNMENT_MAX", "group__aligned.html#ga83c03016066b438f51a8095e9140be06", null ],
+    [ "mi_calloc_aligned", "group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9", null ],
+    [ "mi_calloc_aligned_at", "group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3", null ],
+    [ "mi_malloc_aligned", "group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56", null ],
+    [ "mi_malloc_aligned_at", "group__aligned.html#ga5850da130c936bd77db039dcfbc8295d", null ],
+    [ "mi_realloc_aligned", "group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae", null ],
+    [ "mi_realloc_aligned_at", "group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb", null ],
+    [ "mi_zalloc_aligned", "group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819", null ],
+    [ "mi_zalloc_aligned_at", "group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__analysis.html b/extlib/mimalloc/docs/group__analysis.html
new file mode 100644 (file)
index 0000000..883099f
--- /dev/null
@@ -0,0 +1,379 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Heap Introspection</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__analysis.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#nested-classes">Data Structures</a> &#124;
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Heap Introspection</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Inspect the heap at runtime.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Data Structures</h2></td></tr>
+<tr class="memitem:structmi__heap__area__t"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a></td></tr>
+<tr class="memdesc:structmi__heap__area__t"><td class="mdescLeft">&#160;</td><td class="mdescRight">An area of heap space contains blocks of a single size.  <a href="group__analysis.html#structmi__heap__area__t">More...</a><br /></td></tr>
+<tr class="separator:structmi__heap__area__t"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:gadfa01e2900f0e5d515ad5506b26f6d65"><td class="memItemLeft" align="right" valign="top">typedef bool()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a>(const <a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const <a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a> *area, void *block, size_t block_size, void *arg)</td></tr>
+<tr class="memdesc:gadfa01e2900f0e5d515ad5506b26f6d65"><td class="mdescLeft">&#160;</td><td class="mdescRight">Visitor function passed to <a class="el" href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed" title="Visit all areas and blocks in a heap.">mi_heap_visit_blocks()</a>  <a href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">More...</a><br /></td></tr>
+<tr class="separator:gadfa01e2900f0e5d515ad5506b26f6d65"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gaa862aa8ed8d57d84cae41fc1022d71af"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af">mi_heap_contains_block</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const void *p)</td></tr>
+<tr class="memdesc:gaa862aa8ed8d57d84cae41fc1022d71af"><td class="mdescLeft">&#160;</td><td class="mdescRight">Does a heap contain a pointer to a previously allocated block?  <a href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af">More...</a><br /></td></tr>
+<tr class="separator:gaa862aa8ed8d57d84cae41fc1022d71af"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga0d67c1789faaa15ff366c024fcaf6377"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377">mi_heap_check_owned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const void *p)</td></tr>
+<tr class="memdesc:ga0d67c1789faaa15ff366c024fcaf6377"><td class="mdescLeft">&#160;</td><td class="mdescRight">Check safely if any pointer is part of a heap.  <a href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377">More...</a><br /></td></tr>
+<tr class="separator:ga0d67c1789faaa15ff366c024fcaf6377"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga628c237489c2679af84a4d0d143b3dd5"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5">mi_check_owned</a> (const void *p)</td></tr>
+<tr class="memdesc:ga628c237489c2679af84a4d0d143b3dd5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Check safely if any pointer is part of the default heap of this thread.  <a href="group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5">More...</a><br /></td></tr>
+<tr class="separator:ga628c237489c2679af84a4d0d143b3dd5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga70c46687dc6e9dc98b232b02646f8bed"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed">mi_heap_visit_blocks</a> (const <a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, bool visit_all_blocks, <a class="el" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a> *visitor, void *arg)</td></tr>
+<tr class="memdesc:ga70c46687dc6e9dc98b232b02646f8bed"><td class="mdescLeft">&#160;</td><td class="mdescRight">Visit all areas and blocks in a heap.  <a href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed">More...</a><br /></td></tr>
+<tr class="separator:ga70c46687dc6e9dc98b232b02646f8bed"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>Inspect the heap at runtime. </p>
+<hr/><h2 class="groupheader">Data Structure Documentation</h2>
+<a name="structmi__heap__area__t" id="structmi__heap__area__t"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#structmi__heap__area__t">&#9670;&nbsp;</a></span>mi_heap_area_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">struct mi_heap_area_t</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<div class="textblock"><p>An area of heap space contains blocks of a single size. </p>
+<p>The bytes in freed blocks are <code>committed - used</code>. </p>
+</div><table class="fieldtable">
+<tr><th colspan="3">Data Fields</th></tr>
+<tr><td class="fieldtype">
+<a id="a332a6c14d736a99699d5453a1cb04b41"></a>size_t</td>
+<td class="fieldname">
+block_size</td>
+<td class="fielddoc">
+size in bytes of one block </td></tr>
+<tr><td class="fieldtype">
+<a id="ae0085e6e1cf059a4eb7767e30e9991b8"></a>void *</td>
+<td class="fieldname">
+blocks</td>
+<td class="fielddoc">
+start of the area containing heap blocks </td></tr>
+<tr><td class="fieldtype">
+<a id="ab47526df656d8837ec3e97f11b83f835"></a>size_t</td>
+<td class="fieldname">
+committed</td>
+<td class="fielddoc">
+current committed bytes of this area </td></tr>
+<tr><td class="fieldtype">
+<a id="ae848a3e6840414891035423948ca0383"></a>size_t</td>
+<td class="fieldname">
+reserved</td>
+<td class="fielddoc">
+bytes reserved for this area </td></tr>
+<tr><td class="fieldtype">
+<a id="ab820302c5cd0df133eb8e51650a008b4"></a>size_t</td>
+<td class="fieldname">
+used</td>
+<td class="fielddoc">
+bytes in use by allocated blocks </td></tr>
+</table>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="gadfa01e2900f0e5d515ad5506b26f6d65"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gadfa01e2900f0e5d515ad5506b26f6d65">&#9670;&nbsp;</a></span>mi_block_visit_fun</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef bool() mi_block_visit_fun(const <a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const <a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a> *area, void *block, size_t block_size, void *arg)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Visitor function passed to <a class="el" href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed" title="Visit all areas and blocks in a heap.">mi_heap_visit_blocks()</a> </p>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if ok, <em>false</em> to stop visiting (i.e. break)</dd></dl>
+<p>This function is always first called for every <em>area</em> with <em>block</em> as a <em>NULL</em> pointer. If <em>visit_all_blocks</em> was <em>true</em>, the function is then called for every allocated block in that area. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga628c237489c2679af84a4d0d143b3dd5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga628c237489c2679af84a4d0d143b3dd5">&#9670;&nbsp;</a></span>mi_check_owned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_check_owned </td>
+          <td>(</td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Check safely if any pointer is part of the default heap of this thread. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>Any pointer &ndash; not required to be previously allocated by us. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if <em>p</em> points to a block in default heap of this thread.</dd></dl>
+<p>Note: expensive function, linear in the pages in the heap. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af" title="Does a heap contain a pointer to a previously allocated block?">mi_heap_contains_block()</a> </dd>
+<dd>
+<a class="el" href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05" title="Get the default heap that is used for mi_malloc() et al.">mi_heap_get_default()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga0d67c1789faaa15ff366c024fcaf6377"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0d67c1789faaa15ff366c024fcaf6377">&#9670;&nbsp;</a></span>mi_heap_check_owned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_heap_check_owned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Check safely if any pointer is part of a heap. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">heap</td><td>The heap. </td></tr>
+    <tr><td class="paramname">p</td><td>Any pointer &ndash; not required to be previously allocated by us. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if <em>p</em> points to a block in <em>heap</em>.</dd></dl>
+<p>Note: expensive function, linear in the pages in the heap. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af" title="Does a heap contain a pointer to a previously allocated block?">mi_heap_contains_block()</a> </dd>
+<dd>
+<a class="el" href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05" title="Get the default heap that is used for mi_malloc() et al.">mi_heap_get_default()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gaa862aa8ed8d57d84cae41fc1022d71af"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa862aa8ed8d57d84cae41fc1022d71af">&#9670;&nbsp;</a></span>mi_heap_contains_block()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_heap_contains_block </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Does a heap contain a pointer to a previously allocated block? </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">heap</td><td>The heap. </td></tr>
+    <tr><td class="paramname">p</td><td>Pointer to a previously allocated block (in any heap)&ndash; cannot be some random pointer! </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if the block pointed to by <em>p</em> is in the <em>heap</em>. </dd></dl>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377" title="Check safely if any pointer is part of a heap.">mi_heap_check_owned()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga70c46687dc6e9dc98b232b02646f8bed"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga70c46687dc6e9dc98b232b02646f8bed">&#9670;&nbsp;</a></span>mi_heap_visit_blocks()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_heap_visit_blocks </td>
+          <td>(</td>
+          <td class="paramtype">const <a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>visit_all_blocks</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a> *&#160;</td>
+          <td class="paramname"><em>visitor</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Visit all areas and blocks in a heap. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">heap</td><td>The heap to visit. </td></tr>
+    <tr><td class="paramname">visit_all_blocks</td><td>If <em>true</em> visits all allocated blocks, otherwise <em>visitor</em> is only called for every heap area. </td></tr>
+    <tr><td class="paramname">visitor</td><td>This function is called for every area in the heap (with <em>block</em> as <em>NULL</em>). If <em>visit_all_blocks</em> is <em>true</em>, <em>visitor</em> is also called for every allocated block in every area (with <code>block!=NULL</code>). return <em>false</em> from this function to stop visiting early. </td></tr>
+    <tr><td class="paramname">arg</td><td>Extra argument passed to <em>visitor</em>. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if all areas and blocks were visited. </dd></dl>
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__analysis.js b/extlib/mimalloc/docs/group__analysis.js
new file mode 100644 (file)
index 0000000..3517836
--- /dev/null
@@ -0,0 +1,15 @@
+var group__analysis =
+[
+    [ "mi_heap_area_t", "group__analysis.html#structmi__heap__area__t", [
+      [ "block_size", "group__analysis.html#a332a6c14d736a99699d5453a1cb04b41", null ],
+      [ "blocks", "group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8", null ],
+      [ "committed", "group__analysis.html#ab47526df656d8837ec3e97f11b83f835", null ],
+      [ "reserved", "group__analysis.html#ae848a3e6840414891035423948ca0383", null ],
+      [ "used", "group__analysis.html#ab820302c5cd0df133eb8e51650a008b4", null ]
+    ] ],
+    [ "mi_block_visit_fun", "group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65", null ],
+    [ "mi_check_owned", "group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5", null ],
+    [ "mi_heap_check_owned", "group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377", null ],
+    [ "mi_heap_contains_block", "group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af", null ],
+    [ "mi_heap_visit_blocks", "group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__analysis_structmi__heap__area__t.js b/extlib/mimalloc/docs/group__analysis_structmi__heap__area__t.js
new file mode 100644 (file)
index 0000000..2dbabc5
--- /dev/null
@@ -0,0 +1,8 @@
+var group__analysis_structmi__heap__area__t =
+[
+    [ "block_size", "group__analysis.html#a332a6c14d736a99699d5453a1cb04b41", null ],
+    [ "blocks", "group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8", null ],
+    [ "committed", "group__analysis.html#ab47526df656d8837ec3e97f11b83f835", null ],
+    [ "reserved", "group__analysis.html#ae848a3e6840414891035423948ca0383", null ],
+    [ "used", "group__analysis.html#ab820302c5cd0df133eb8e51650a008b4", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__cpp.html b/extlib/mimalloc/docs/group__cpp.html
new file mode 100644 (file)
index 0000000..e81179f
--- /dev/null
@@ -0,0 +1,393 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: C++ wrappers</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__cpp.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#nested-classes">Data Structures</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">C++ wrappers</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Data Structures</h2></td></tr>
+<tr class="memitem:structmi__stl__allocator"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator&lt; T &gt;</a></td></tr>
+<tr class="memdesc:structmi__stl__allocator"><td class="mdescLeft">&#160;</td><td class="mdescRight"><em>std::allocator</em> implementation for mimalloc for use in STL containers.  <a href="group__cpp.html#structmi__stl__allocator">More...</a><br /></td></tr>
+<tr class="separator:structmi__stl__allocator"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">mi_new</a> (std::size_t n) noexcept(false)</td></tr>
+<tr class="memdesc:gaad048a9fce3d02c5909cd05c6ec24545"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure.  <a href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">More...</a><br /></td></tr>
+<tr class="separator:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">mi_new_n</a> (size_t count, size_t size) noexcept(false)</td></tr>
+<tr class="memdesc:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6" title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure.  <a href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">More...</a><br /></td></tr>
+<tr class="separator:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a> (std::size_t n, std::align_val_t alignment) noexcept(false)</td></tr>
+<tr class="memdesc:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56" title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure.  <a href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">More...</a><br /></td></tr>
+<tr class="separator:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">mi_new_nothrow</a> (size_t n)</td></tr>
+<tr class="memdesc:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <code>mi_malloc</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure.  <a href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">More...</a><br /></td></tr>
+<tr class="separator:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gab5e29558926d934c3f1cae8c815f942c"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a> (size_t n, size_t alignment)</td></tr>
+<tr class="memdesc:gab5e29558926d934c3f1cae8c815f942c"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <code>mi_malloc_aligned</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure.  <a href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">More...</a><br /></td></tr>
+<tr class="separator:gab5e29558926d934c3f1cae8c815f942c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaab78a32f55149e9fbf432d5288e38e1e"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">mi_new_realloc</a> (void *p, size_t newsize)</td></tr>
+<tr class="memdesc:gaab78a32f55149e9fbf432d5288e38e1e"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6" title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure.  <a href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">More...</a><br /></td></tr>
+<tr class="separator:gaab78a32f55149e9fbf432d5288e38e1e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">mi_new_reallocn</a> (void *p, size_t newcount, size_t size)</td></tr>
+<tr class="memdesc:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853" title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure.  <a href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">More...</a><br /></td></tr>
+<tr class="separator:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure. </p>
+<p>Note: use the <code>mimalloc-new-delete.h</code> header to override the <em>new</em> and <em>delete</em> operators globally. The wrappers here are mostly for convience for library writers that need to interface with mimalloc from C++. </p>
+<hr/><h2 class="groupheader">Data Structure Documentation</h2>
+<a name="structmi__stl__allocator" id="structmi__stl__allocator"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#structmi__stl__allocator">&#9670;&nbsp;</a></span>mi_stl_allocator</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">struct mi_stl_allocator</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<div class="textblock"><h3>template&lt;class T&gt;<br />
+struct mi_stl_allocator&lt; T &gt;</h3>
+
+<p><em>std::allocator</em> implementation for mimalloc for use in STL containers. </p>
+<p>For example: </p><div class="fragment"><div class="line">std::vector&lt;int, mi_stl_allocator&lt;int&gt; &gt; vec;</div>
+<div class="line">vec.push_back(1);</div>
+<div class="line">vec.pop_back();</div>
+</div><!-- fragment --> </div>
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gaad048a9fce3d02c5909cd05c6ec24545"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaad048a9fce3d02c5909cd05c6ec24545">&#9670;&nbsp;</a></span>mi_new()</h2>
+
+<div class="memitem">
+<div class="memproto">
+<table class="mlabels">
+  <tr>
+  <td class="mlabels-left">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new </td>
+          <td>(</td>
+          <td class="paramtype">std::size_t&#160;</td>
+          <td class="paramname"><em>n</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+  </td>
+  <td class="mlabels-right">
+<span class="mlabels"><span class="mlabel">noexcept</span></span>  </td>
+  </tr>
+</table>
+</div><div class="memdoc">
+
+<p>like <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
+
+</div>
+</div>
+<a id="gaef2c2bdb4f70857902d3c8903ac095f3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaef2c2bdb4f70857902d3c8903ac095f3">&#9670;&nbsp;</a></span>mi_new_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+<table class="mlabels">
+  <tr>
+  <td class="mlabels-left">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_aligned </td>
+          <td>(</td>
+          <td class="paramtype">std::size_t&#160;</td>
+          <td class="paramname"><em>n</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">std::align_val_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+  </td>
+  <td class="mlabels-right">
+<span class="mlabels"><span class="mlabel">noexcept</span></span>  </td>
+  </tr>
+</table>
+</div><div class="memdoc">
+
+<p>like <a class="el" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56" title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
+
+</div>
+</div>
+<a id="gab5e29558926d934c3f1cae8c815f942c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab5e29558926d934c3f1cae8c815f942c">&#9670;&nbsp;</a></span>mi_new_aligned_nothrow()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_aligned_nothrow </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>n</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>like <code>mi_malloc_aligned</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. </p>
+
+</div>
+</div>
+<a id="gae7bc4f56cd57ed3359060ff4f38bda81"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae7bc4f56cd57ed3359060ff4f38bda81">&#9670;&nbsp;</a></span>mi_new_n()</h2>
+
+<div class="memitem">
+<div class="memproto">
+<table class="mlabels">
+  <tr>
+  <td class="mlabels-left">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_n </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+  </td>
+  <td class="mlabels-right">
+<span class="mlabels"><span class="mlabel">noexcept</span></span>  </td>
+  </tr>
+</table>
+</div><div class="memdoc">
+
+<p>like <a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6" title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
+
+</div>
+</div>
+<a id="gaeaded64eda71ed6b1d569d3e723abc4a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaeaded64eda71ed6b1d569d3e723abc4a">&#9670;&nbsp;</a></span>mi_new_nothrow()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_nothrow </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>n</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>like <code>mi_malloc</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. </p>
+
+</div>
+</div>
+<a id="gaab78a32f55149e9fbf432d5288e38e1e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaab78a32f55149e9fbf432d5288e38e1e">&#9670;&nbsp;</a></span>mi_new_realloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_realloc </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>like <a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6" title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
+
+</div>
+</div>
+<a id="ga756f4b2bc6a7ecd0a90baea8e90c7907"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga756f4b2bc6a7ecd0a90baea8e90c7907">&#9670;&nbsp;</a></span>mi_new_reallocn()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_new_reallocn </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>like <a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853" title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__cpp.js b/extlib/mimalloc/docs/group__cpp.js
new file mode 100644 (file)
index 0000000..2070664
--- /dev/null
@@ -0,0 +1,11 @@
+var group__cpp =
+[
+    [ "mi_stl_allocator", "group__cpp.html#structmi__stl__allocator", null ],
+    [ "mi_new", "group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545", null ],
+    [ "mi_new_aligned", "group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3", null ],
+    [ "mi_new_aligned_nothrow", "group__cpp.html#gab5e29558926d934c3f1cae8c815f942c", null ],
+    [ "mi_new_n", "group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81", null ],
+    [ "mi_new_nothrow", "group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a", null ],
+    [ "mi_new_realloc", "group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e", null ],
+    [ "mi_new_reallocn", "group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__extended.html b/extlib/mimalloc/docs/group__extended.html
new file mode 100644 (file)
index 0000000..e549911
--- /dev/null
@@ -0,0 +1,1078 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Extended Functions</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__extended.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#define-members">Macros</a> &#124;
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Extended Functions</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Extended functionality.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga1ea64283508718d9d645c38efc2f4305"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305">MI_SMALL_SIZE_MAX</a></td></tr>
+<tr class="memdesc:ga1ea64283508718d9d645c38efc2f4305"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum size allowed for small allocations in <a class="el" href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99" title="Allocate a small object.">mi_malloc_small</a> and <a class="el" href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152" title="Allocate a zero initialized small object.">mi_zalloc_small</a> (usually <code>128*sizeof(void*)</code> (= 1KB on 64-bit systems))  <a href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305">More...</a><br /></td></tr>
+<tr class="separator:ga1ea64283508718d9d645c38efc2f4305"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga299dae78d25ce112e384a98b7309c5be"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat, void *arg)</td></tr>
+<tr class="memdesc:ga299dae78d25ce112e384a98b7309c5be"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of deferred free functions.  <a href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">More...</a><br /></td></tr>
+<tr class="separator:ga299dae78d25ce112e384a98b7309c5be"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gad823d23444a4b77a40f66bf075a98a0c"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>(const char *msg, void *arg)</td></tr>
+<tr class="memdesc:gad823d23444a4b77a40f66bf075a98a0c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of output functions.  <a href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">More...</a><br /></td></tr>
+<tr class="separator:gad823d23444a4b77a40f66bf075a98a0c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga251d369cda3f1c2a955c555486ed90e5"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a>(int err, void *arg)</td></tr>
+<tr class="memdesc:ga251d369cda3f1c2a955c555486ed90e5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of error callback functions.  <a href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">More...</a><br /></td></tr>
+<tr class="separator:ga251d369cda3f1c2a955c555486ed90e5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga7136c2e55cb22c98ecf95d08d6debb99"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99">mi_malloc_small</a> (size_t size)</td></tr>
+<tr class="memdesc:ga7136c2e55cb22c98ecf95d08d6debb99"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a small object.  <a href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99">More...</a><br /></td></tr>
+<tr class="separator:ga7136c2e55cb22c98ecf95d08d6debb99"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga220f29f40a44404b0061c15bc1c31152"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152">mi_zalloc_small</a> (size_t size)</td></tr>
+<tr class="memdesc:ga220f29f40a44404b0061c15bc1c31152"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a zero initialized small object.  <a href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152">More...</a><br /></td></tr>
+<tr class="separator:ga220f29f40a44404b0061c15bc1c31152"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga089c859d9eddc5f9b4bd946cd53cebee"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee">mi_usable_size</a> (void *p)</td></tr>
+<tr class="memdesc:ga089c859d9eddc5f9b4bd946cd53cebee"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return the available bytes in a memory block.  <a href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee">More...</a><br /></td></tr>
+<tr class="separator:ga089c859d9eddc5f9b4bd946cd53cebee"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gac057927cd06c854b45fe7847e921bd47"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gac057927cd06c854b45fe7847e921bd47">mi_good_size</a> (size_t size)</td></tr>
+<tr class="memdesc:gac057927cd06c854b45fe7847e921bd47"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return the used allocation size.  <a href="group__extended.html#gac057927cd06c854b45fe7847e921bd47">More...</a><br /></td></tr>
+<tr class="separator:gac057927cd06c854b45fe7847e921bd47"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga421430e2226d7d468529cec457396756"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a> (bool force)</td></tr>
+<tr class="memdesc:ga421430e2226d7d468529cec457396756"><td class="mdescLeft">&#160;</td><td class="mdescRight">Eagerly free memory.  <a href="group__extended.html#ga421430e2226d7d468529cec457396756">More...</a><br /></td></tr>
+<tr class="separator:ga421430e2226d7d468529cec457396756"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga2d126e5c62d3badc35445e5d84166df2"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">mi_stats_print</a> (void *out)</td></tr>
+<tr class="memdesc:ga2d126e5c62d3badc35445e5d84166df2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deprecated.  <a href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">More...</a><br /></td></tr>
+<tr class="separator:ga2d126e5c62d3badc35445e5d84166df2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga537f13b299ddf801e49a5a94fde02c79"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga537f13b299ddf801e49a5a94fde02c79">mi_stats_print_out</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
+<tr class="memdesc:ga537f13b299ddf801e49a5a94fde02c79"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print the main statistics.  <a href="group__extended.html#ga537f13b299ddf801e49a5a94fde02c79">More...</a><br /></td></tr>
+<tr class="separator:ga537f13b299ddf801e49a5a94fde02c79"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a> (void)</td></tr>
+<tr class="memdesc:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reset statistics.  <a href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">More...</a><br /></td></tr>
+<tr class="separator:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">mi_stats_merge</a> (void)</td></tr>
+<tr class="memdesc:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Merge thread local statistics with the main statistics and reset.  <a href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">More...</a><br /></td></tr>
+<tr class="separator:ga854b1de8cb067c7316286c28b2fcd3d1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">mi_thread_init</a> (void)</td></tr>
+<tr class="memdesc:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="mdescLeft">&#160;</td><td class="mdescRight">Initialize mimalloc on a thread.  <a href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">More...</a><br /></td></tr>
+<tr class="separator:gaf8e73efc2cbca9ebfdfb166983a04c17"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a> (void)</td></tr>
+<tr class="memdesc:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Uninitialize mimalloc on a thread.  <a href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">More...</a><br /></td></tr>
+<tr class="separator:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gab1dac8476c46cb9eecab767eb40c1525"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">mi_thread_stats_print_out</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
+<tr class="memdesc:gab1dac8476c46cb9eecab767eb40c1525"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print out heap statistics for this thread.  <a href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">More...</a><br /></td></tr>
+<tr class="separator:gab1dac8476c46cb9eecab767eb40c1525"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3460a6ca91af97be4058f523d3cb8ece"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">mi_register_deferred_free</a> (<a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a> *deferred_free, void *arg)</td></tr>
+<tr class="memdesc:ga3460a6ca91af97be4058f523d3cb8ece"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register a deferred free function.  <a href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">More...</a><br /></td></tr>
+<tr class="separator:ga3460a6ca91af97be4058f523d3cb8ece"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae5b17ff027cd2150b43a33040250cf3f"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">mi_register_output</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
+<tr class="memdesc:gae5b17ff027cd2150b43a33040250cf3f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register an output function.  <a href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">More...</a><br /></td></tr>
+<tr class="separator:gae5b17ff027cd2150b43a33040250cf3f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">mi_register_error</a> (<a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a> *errfun, void *arg)</td></tr>
+<tr class="memdesc:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register an error callback function.  <a href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">More...</a><br /></td></tr>
+<tr class="separator:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a> (const void *p)</td></tr>
+<tr class="memdesc:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is a pointer part of our heap?  <a href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">More...</a><br /></td></tr>
+<tr class="separator:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga00ec3324b6b2591c7fe3677baa30a767"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767">mi_reserve_os_memory</a> (size_t size, bool commit, bool allow_large)</td></tr>
+<tr class="memdesc:ga00ec3324b6b2591c7fe3677baa30a767"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve OS memory for use by mimalloc.  <a href="group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767">More...</a><br /></td></tr>
+<tr class="separator:ga00ec3324b6b2591c7fe3677baa30a767"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4c6486a1fdcd7a423b5f25fe4be8e0cf"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">mi_manage_os_memory</a> (void *start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node)</td></tr>
+<tr class="memdesc:ga4c6486a1fdcd7a423b5f25fe4be8e0cf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Manage a particular memory area for use by mimalloc.  <a href="group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">More...</a><br /></td></tr>
+<tr class="separator:ga4c6486a1fdcd7a423b5f25fe4be8e0cf"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">mi_reserve_huge_os_pages_interleave</a> (size_t pages, size_t numa_nodes, size_t timeout_msecs)</td></tr>
+<tr class="memdesc:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds.  <a href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">More...</a><br /></td></tr>
+<tr class="separator:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7795a13d20087447281858d2c771cca1"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga7795a13d20087447281858d2c771cca1">mi_reserve_huge_os_pages_at</a> (size_t pages, int numa_node, size_t timeout_msecs)</td></tr>
+<tr class="memdesc:ga7795a13d20087447281858d2c771cca1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds.  <a href="group__extended.html#ga7795a13d20087447281858d2c771cca1">More...</a><br /></td></tr>
+<tr class="separator:ga7795a13d20087447281858d2c771cca1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaad25050b19f30cd79397b227e0157a3f"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a> ()</td></tr>
+<tr class="memdesc:gaad25050b19f30cd79397b227e0157a3f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is the C runtime <em>malloc</em> API redirected?  <a href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">More...</a><br /></td></tr>
+<tr class="separator:gaad25050b19f30cd79397b227e0157a3f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7d862c2affd5790381da14eb102a364d"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga7d862c2affd5790381da14eb102a364d">mi_process_info</a> (size_t *elapsed_msecs, size_t *user_msecs, size_t *system_msecs, size_t *current_rss, size_t *peak_rss, size_t *current_commit, size_t *peak_commit, size_t *page_faults)</td></tr>
+<tr class="memdesc:ga7d862c2affd5790381da14eb102a364d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Return process information (time and memory usage).  <a href="group__extended.html#ga7d862c2affd5790381da14eb102a364d">More...</a><br /></td></tr>
+<tr class="separator:ga7d862c2affd5790381da14eb102a364d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>Extended functionality. </p>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga1ea64283508718d9d645c38efc2f4305"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1ea64283508718d9d645c38efc2f4305">&#9670;&nbsp;</a></span>MI_SMALL_SIZE_MAX</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define MI_SMALL_SIZE_MAX</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum size allowed for small allocations in <a class="el" href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99" title="Allocate a small object.">mi_malloc_small</a> and <a class="el" href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152" title="Allocate a zero initialized small object.">mi_zalloc_small</a> (usually <code>128*sizeof(void*)</code> (= 1KB on 64-bit systems)) </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga299dae78d25ce112e384a98b7309c5be"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga299dae78d25ce112e384a98b7309c5be">&#9670;&nbsp;</a></span>mi_deferred_free_fun</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void() mi_deferred_free_fun(bool force, unsigned long long heartbeat, void *arg)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Type of deferred free functions. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">force</td><td>If <em>true</em> all outstanding items should be freed. </td></tr>
+    <tr><td class="paramname">heartbeat</td><td>A monotonically increasing count. </td></tr>
+    <tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece" title="Register a deferred free function.">mi_register_deferred_free</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga251d369cda3f1c2a955c555486ed90e5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga251d369cda3f1c2a955c555486ed90e5">&#9670;&nbsp;</a></span>mi_error_fun</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void() mi_error_fun(int err, void *arg)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Type of error callback functions. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">err</td><td>Error code (see <a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45" title="Register an error callback function.">mi_register_error()</a> for a complete list). </td></tr>
+    <tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45" title="Register an error callback function.">mi_register_error()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gad823d23444a4b77a40f66bf075a98a0c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad823d23444a4b77a40f66bf075a98a0c">&#9670;&nbsp;</a></span>mi_output_fun</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void() mi_output_fun(const char *msg, void *arg)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Type of output functions. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">msg</td><td>Message to output. </td></tr>
+    <tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f" title="Register an output function.">mi_register_output()</a> </dd></dl>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga421430e2226d7d468529cec457396756"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga421430e2226d7d468529cec457396756">&#9670;&nbsp;</a></span>mi_collect()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_collect </td>
+          <td>(</td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>force</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Eagerly free memory. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">force</td><td>If <em>true</em>, aggressively return memory to the OS (can be expensive!)</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Regular code should not have to call this function. It can be beneficial in very narrow circumstances; in particular, when a long running thread allocates a lot of blocks that are freed by other threads it may improve resource usage by calling this every once in a while. </p>
+
+</div>
+</div>
+<a id="gac057927cd06c854b45fe7847e921bd47"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac057927cd06c854b45fe7847e921bd47">&#9670;&nbsp;</a></span>mi_good_size()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t mi_good_size </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Return the used allocation size. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>The minimal required size in bytes. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>the size <code>n</code> that will be allocated, where <code>n &gt;= size</code>.</dd></dl>
+<p>Generally, <code>mi_usable_size(mi_malloc(size)) == mi_good_size(size)</code>. This can be used to reduce internal wasted space when allocating buffers for example.</p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee" title="Return the available bytes in a memory block.">mi_usable_size()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga5f071b10d4df1c3658e04e7fd67a94e6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5f071b10d4df1c3658e04e7fd67a94e6">&#9670;&nbsp;</a></span>mi_is_in_heap_region()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_is_in_heap_region </td>
+          <td>(</td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Is a pointer part of our heap? </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>The pointer to check. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if this is a pointer into our heap. This function is relatively fast. </dd></dl>
+
+</div>
+</div>
+<a id="gaad25050b19f30cd79397b227e0157a3f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaad25050b19f30cd79397b227e0157a3f">&#9670;&nbsp;</a></span>mi_is_redirected()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_is_redirected </td>
+          <td>(</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Is the C runtime <em>malloc</em> API redirected? </p>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if all malloc API calls are redirected to mimalloc.</dd></dl>
+<p>Currenty only used on Windows. </p>
+
+</div>
+</div>
+<a id="ga7136c2e55cb22c98ecf95d08d6debb99"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7136c2e55cb22c98ecf95d08d6debb99">&#9670;&nbsp;</a></span>mi_malloc_small()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_malloc_small </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a small object. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>The size in bytes, can be at most <a class="el" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305" title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX</a>. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>a pointer to newly allocated memory of at least <em>size</em> bytes, or <em>NULL</em> if out of memory. This function is meant for use in run-time systems for best performance and does not check if <em>size</em> was indeed small &ndash; use with care! </dd></dl>
+
+</div>
+</div>
+<a id="ga4c6486a1fdcd7a423b5f25fe4be8e0cf"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">&#9670;&nbsp;</a></span>mi_manage_os_memory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_manage_os_memory </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>start</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>is_committed</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>is_large</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>is_zero</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&#160;</td>
+          <td class="paramname"><em>numa_node</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Manage a particular memory area for use by mimalloc. </p>
+<p>This is just like <code>mi_reserve_os_memory</code> except that the area should already be allocated in some manner and available for use my mimalloc. </p><dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">start</td><td>Start of the memory area </td></tr>
+    <tr><td class="paramname">size</td><td>The size of the memory area. </td></tr>
+    <tr><td class="paramname">commit</td><td>Is the area already committed? </td></tr>
+    <tr><td class="paramname">is_large</td><td>Does it consist of large OS pages? Set this to <em>true</em> as well for memory that should not be decommitted or protected (like rdma etc.) </td></tr>
+    <tr><td class="paramname">is_zero</td><td>Does the area consists of zero's? </td></tr>
+    <tr><td class="paramname">numa_node</td><td>Possible associated numa node or <code>-1</code>. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>true</em> if successful, and <em>false</em> on error. </dd></dl>
+
+</div>
+</div>
+<a id="ga7d862c2affd5790381da14eb102a364d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7d862c2affd5790381da14eb102a364d">&#9670;&nbsp;</a></span>mi_process_info()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_process_info </td>
+          <td>(</td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>elapsed_msecs</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>user_msecs</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>system_msecs</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>current_rss</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>peak_rss</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>current_commit</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>peak_commit</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>page_faults</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Return process information (time and memory usage). </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">elapsed_msecs</td><td>Optional. Elapsed wall-clock time of the process in milli-seconds. </td></tr>
+    <tr><td class="paramname">user_msecs</td><td>Optional. User time in milli-seconds (as the sum over all threads). </td></tr>
+    <tr><td class="paramname">system_msecs</td><td>Optional. System time in milli-seconds. </td></tr>
+    <tr><td class="paramname">current_rss</td><td>Optional. Current working set size (touched pages). </td></tr>
+    <tr><td class="paramname">peak_rss</td><td>Optional. Peak working set size (touched pages). </td></tr>
+    <tr><td class="paramname">current_commit</td><td>Optional. Current committed memory (backed by the page file). </td></tr>
+    <tr><td class="paramname">peak_commit</td><td>Optional. Peak committed memory (backed by the page file). </td></tr>
+    <tr><td class="paramname">page_faults</td><td>Optional. Count of hard page faults.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>The <em>current_rss</em> is precise on Windows and MacOSX; other systems estimate this using <em>current_commit</em>. The <em>commit</em> is precise on Windows but estimated on other systems as the amount of read/write accessible memory reserved by mimalloc. </p>
+
+</div>
+</div>
+<a id="ga3460a6ca91af97be4058f523d3cb8ece"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3460a6ca91af97be4058f523d3cb8ece">&#9670;&nbsp;</a></span>mi_register_deferred_free()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_register_deferred_free </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a> *&#160;</td>
+          <td class="paramname"><em>deferred_free</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Register a deferred free function. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">deferred_free</td><td>Address of a deferred free-ing function or <em>NULL</em> to unregister. </td></tr>
+    <tr><td class="paramname">arg</td><td>Argument that will be passed on to the deferred free function.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Some runtime systems use deferred free-ing, for example when using reference counting to limit the worst case free time. Such systems can register (re-entrant) deferred free function to free more memory on demand. When the <em>force</em> parameter is <em>true</em> all possible memory should be freed. The per-thread <em>heartbeat</em> parameter is monotonically increasing and guaranteed to be deterministic if the program allocates deterministically. The <em>deferred_free</em> function is guaranteed to be called deterministically after some number of allocations (regardless of freeing or available free memory). At most one <em>deferred_free</em> function can be active. </p>
+
+</div>
+</div>
+<a id="gaa1d55e0e894be240827e5d87ec3a1f45"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa1d55e0e894be240827e5d87ec3a1f45">&#9670;&nbsp;</a></span>mi_register_error()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_register_error </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a> *&#160;</td>
+          <td class="paramname"><em>errfun</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Register an error callback function. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">errfun</td><td>The error function that is called on an error (use <em>NULL</em> for default) </td></tr>
+    <tr><td class="paramname">arg</td><td>Extra argument that will be passed on to the error function.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>The <em>errfun</em> function is called on an error in mimalloc after emitting an error message (through the output function). It as always legal to just return from the <em>errfun</em> function in which case allocation functions generally return <em>NULL</em> or ignore the condition. The default function only calls abort() when compiled in secure mode with an <em>EFAULT</em> error. The possible error codes are:</p><ul>
+<li><em>EAGAIN:</em> Double free was detected (only in debug and secure mode).</li>
+<li><em>EFAULT:</em> Corrupted free list or meta-data was detected (only in debug and secure mode).</li>
+<li><em>ENOMEM:</em> Not enough memory available to satisfy the request.</li>
+<li><em>EOVERFLOW:</em> Too large a request, for example in <a class="el" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d" title="Allocate zero-initialized count elements of size bytes.">mi_calloc()</a>, the <em>count</em> and <em>size</em> parameters are too large.</li>
+<li><em>EINVAL:</em> Trying to free or re-allocate an invalid pointer. </li>
+</ul>
+
+</div>
+</div>
+<a id="gae5b17ff027cd2150b43a33040250cf3f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae5b17ff027cd2150b43a33040250cf3f">&#9670;&nbsp;</a></span>mi_register_output()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_register_output </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
+          <td class="paramname"><em>out</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Register an output function. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">out</td><td>The output function, use <code>NULL</code> to output to stderr. </td></tr>
+    <tr><td class="paramname">arg</td><td>Argument that will be passed on to the output function.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>The <code>out</code> function is called to output any information from mimalloc, like verbose or warning messages. </p>
+
+</div>
+</div>
+<a id="ga7795a13d20087447281858d2c771cca1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7795a13d20087447281858d2c771cca1">&#9670;&nbsp;</a></span>mi_reserve_huge_os_pages_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi_reserve_huge_os_pages_at </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>pages</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">int&#160;</td>
+          <td class="paramname"><em>numa_node</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>timeout_msecs</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
+    <tr><td class="paramname">numa_node</td><td>The NUMA node where the memory is reserved (start at 0). </td></tr>
+    <tr><td class="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
+<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
+
+</div>
+</div>
+<a id="ga3132f521fb756fc0e8ec0b74fb58df50"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3132f521fb756fc0e8ec0b74fb58df50">&#9670;&nbsp;</a></span>mi_reserve_huge_os_pages_interleave()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi_reserve_huge_os_pages_interleave </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>pages</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>numa_nodes</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>timeout_msecs</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
+    <tr><td class="paramname">numa_nodes</td><td>The number of nodes do evenly divide the pages over, or 0 for using the actual number of NUMA nodes. </td></tr>
+    <tr><td class="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
+<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
+
+</div>
+</div>
+<a id="ga00ec3324b6b2591c7fe3677baa30a767"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga00ec3324b6b2591c7fe3677baa30a767">&#9670;&nbsp;</a></span>mi_reserve_os_memory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi_reserve_os_memory </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>commit</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>allow_large</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Reserve OS memory for use by mimalloc. </p>
+<p>Reserved areas are used before allocating from the OS again. By reserving a large area upfront, allocation can be more efficient, and can be better managed on systems without <code>mmap</code>/<code>VirtualAlloc</code> (like WASM for example). </p><dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>The size to reserve. </td></tr>
+    <tr><td class="paramname">commit</td><td>Commit the memory upfront. </td></tr>
+    <tr><td class="paramname">allow_large</td><td>Allow large OS pages (2MiB) to be used? </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><em>0</em> if successful, and an error code otherwise (e.g. <code>ENOMEM</code>). </dd></dl>
+
+</div>
+</div>
+<a id="ga854b1de8cb067c7316286c28b2fcd3d1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga854b1de8cb067c7316286c28b2fcd3d1">&#9670;&nbsp;</a></span>mi_stats_merge()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_stats_merge </td>
+          <td>(</td>
+          <td class="paramtype">void&#160;</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Merge thread local statistics with the main statistics and reset. </p>
+
+</div>
+</div>
+<a id="ga2d126e5c62d3badc35445e5d84166df2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga2d126e5c62d3badc35445e5d84166df2">&#9670;&nbsp;</a></span>mi_stats_print()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_stats_print </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>out</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Deprecated. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">out</td><td>Ignored, outputs to the registered output function or stderr by default.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Most detailed when using a debug build. </p>
+
+</div>
+</div>
+<a id="ga537f13b299ddf801e49a5a94fde02c79"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga537f13b299ddf801e49a5a94fde02c79">&#9670;&nbsp;</a></span>mi_stats_print_out()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_stats_print_out </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
+          <td class="paramname"><em>out</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Print the main statistics. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">out</td><td>An output function or <em>NULL</em> for the default. </td></tr>
+    <tr><td class="paramname">arg</td><td>Optional argument passed to <em>out</em> (if not <em>NULL</em>)</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Most detailed when using a debug build. </p>
+
+</div>
+</div>
+<a id="ga3bb8468b8cfcc6e2a61d98aee85c5f99"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3bb8468b8cfcc6e2a61d98aee85c5f99">&#9670;&nbsp;</a></span>mi_stats_reset()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_stats_reset </td>
+          <td>(</td>
+          <td class="paramtype">void&#160;</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Reset statistics. </p>
+
+</div>
+</div>
+<a id="ga0ae4581e85453456a0d658b2b98bf7bf"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0ae4581e85453456a0d658b2b98bf7bf">&#9670;&nbsp;</a></span>mi_thread_done()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_thread_done </td>
+          <td>(</td>
+          <td class="paramtype">void&#160;</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Uninitialize mimalloc on a thread. </p>
+<p>Should not be used as on most systems (pthreads, windows) this is done automatically. Ensures that any memory that is not freed yet (but will be freed by other threads in the future) is properly handled. </p>
+
+</div>
+</div>
+<a id="gaf8e73efc2cbca9ebfdfb166983a04c17"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf8e73efc2cbca9ebfdfb166983a04c17">&#9670;&nbsp;</a></span>mi_thread_init()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_thread_init </td>
+          <td>(</td>
+          <td class="paramtype">void&#160;</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Initialize mimalloc on a thread. </p>
+<p>Should not be used as on most systems (pthreads, windows) this is done automatically. </p>
+
+</div>
+</div>
+<a id="gab1dac8476c46cb9eecab767eb40c1525"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab1dac8476c46cb9eecab767eb40c1525">&#9670;&nbsp;</a></span>mi_thread_stats_print_out()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_thread_stats_print_out </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
+          <td class="paramname"><em>out</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>arg</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Print out heap statistics for this thread. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">out</td><td>An output function or <em>NULL</em> for the default. </td></tr>
+    <tr><td class="paramname">arg</td><td>Optional argument passed to <em>out</em> (if not <em>NULL</em>)</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Most detailed when using a debug build. </p>
+
+</div>
+</div>
+<a id="ga089c859d9eddc5f9b4bd946cd53cebee"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga089c859d9eddc5f9b4bd946cd53cebee">&#9670;&nbsp;</a></span>mi_usable_size()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t mi_usable_size </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Return the available bytes in a memory block. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>Pointer to previously allocated memory (or <em>NULL</em>) </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>Returns the available bytes in the memory block, or 0 if <em>p</em> was <em>NULL</em>.</dd></dl>
+<p>The returned size can be used to call <em>mi_expand</em> successfully. The returned size is always at least equal to the allocated size of <em>p</em>, and, in the current design, should be less than 16.7% more.</p>
+<dl class="section see"><dt>See also</dt><dd><a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=vs-2017">_msize</a> (Windows) </dd>
+<dd>
+<a href="http://man7.org/linux/man-pages/man3/malloc_usable_size.3.html">malloc_usable_size</a> (Linux) </dd>
+<dd>
+<a class="el" href="group__extended.html#gac057927cd06c854b45fe7847e921bd47" title="Return the used allocation size.">mi_good_size()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga220f29f40a44404b0061c15bc1c31152"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga220f29f40a44404b0061c15bc1c31152">&#9670;&nbsp;</a></span>mi_zalloc_small()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_zalloc_small </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a zero initialized small object. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>The size in bytes, can be at most <a class="el" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305" title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX</a>. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>a pointer to newly allocated zero-initialized memory of at least <em>size</em> bytes, or <em>NULL</em> if out of memory. This function is meant for use in run-time systems for best performance and does not check if <em>size</em> was indeed small &ndash; use with care! </dd></dl>
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__extended.js b/extlib/mimalloc/docs/group__extended.js
new file mode 100644 (file)
index 0000000..c217aac
--- /dev/null
@@ -0,0 +1,29 @@
+var group__extended =
+[
+    [ "MI_SMALL_SIZE_MAX", "group__extended.html#ga1ea64283508718d9d645c38efc2f4305", null ],
+    [ "mi_deferred_free_fun", "group__extended.html#ga299dae78d25ce112e384a98b7309c5be", null ],
+    [ "mi_error_fun", "group__extended.html#ga251d369cda3f1c2a955c555486ed90e5", null ],
+    [ "mi_output_fun", "group__extended.html#gad823d23444a4b77a40f66bf075a98a0c", null ],
+    [ "mi_collect", "group__extended.html#ga421430e2226d7d468529cec457396756", null ],
+    [ "mi_good_size", "group__extended.html#gac057927cd06c854b45fe7847e921bd47", null ],
+    [ "mi_is_in_heap_region", "group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6", null ],
+    [ "mi_is_redirected", "group__extended.html#gaad25050b19f30cd79397b227e0157a3f", null ],
+    [ "mi_malloc_small", "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99", null ],
+    [ "mi_manage_os_memory", "group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf", null ],
+    [ "mi_process_info", "group__extended.html#ga7d862c2affd5790381da14eb102a364d", null ],
+    [ "mi_register_deferred_free", "group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece", null ],
+    [ "mi_register_error", "group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45", null ],
+    [ "mi_register_output", "group__extended.html#gae5b17ff027cd2150b43a33040250cf3f", null ],
+    [ "mi_reserve_huge_os_pages_at", "group__extended.html#ga7795a13d20087447281858d2c771cca1", null ],
+    [ "mi_reserve_huge_os_pages_interleave", "group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50", null ],
+    [ "mi_reserve_os_memory", "group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767", null ],
+    [ "mi_stats_merge", "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1", null ],
+    [ "mi_stats_print", "group__extended.html#ga2d126e5c62d3badc35445e5d84166df2", null ],
+    [ "mi_stats_print_out", "group__extended.html#ga537f13b299ddf801e49a5a94fde02c79", null ],
+    [ "mi_stats_reset", "group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99", null ],
+    [ "mi_thread_done", "group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf", null ],
+    [ "mi_thread_init", "group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17", null ],
+    [ "mi_thread_stats_print_out", "group__extended.html#gab1dac8476c46cb9eecab767eb40c1525", null ],
+    [ "mi_usable_size", "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee", null ],
+    [ "mi_zalloc_small", "group__extended.html#ga220f29f40a44404b0061c15bc1c31152", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__heap.html b/extlib/mimalloc/docs/group__heap.html
new file mode 100644 (file)
index 0000000..0f21ea4
--- /dev/null
@@ -0,0 +1,1074 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Heap Allocation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__heap.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Heap Allocation</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>First-class heaps that can be destroyed in one go.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga34a47cde5a5b38c29f1aa3c5e76943c2"><td class="memItemLeft" align="right" valign="top">typedef struct mi_heap_s&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a></td></tr>
+<tr class="memdesc:ga34a47cde5a5b38c29f1aa3c5e76943c2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of first-class heaps.  <a href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">More...</a><br /></td></tr>
+<tr class="separator:ga34a47cde5a5b38c29f1aa3c5e76943c2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga766f672ba56f2fbfeb9d9dbb0b7f6b11"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">mi_heap_new</a> ()</td></tr>
+<tr class="memdesc:ga766f672ba56f2fbfeb9d9dbb0b7f6b11"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a new heap that can be used for allocation.  <a href="group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">More...</a><br /></td></tr>
+<tr class="separator:ga766f672ba56f2fbfeb9d9dbb0b7f6b11"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga2ab1af8d438819b55319c7ef51d1e409"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409">mi_heap_delete</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap)</td></tr>
+<tr class="memdesc:ga2ab1af8d438819b55319c7ef51d1e409"><td class="mdescLeft">&#160;</td><td class="mdescRight">Delete a previously allocated heap.  <a href="group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409">More...</a><br /></td></tr>
+<tr class="separator:ga2ab1af8d438819b55319c7ef51d1e409"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga9f9c0844edb9717f4feacd79116b8e0d"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d">mi_heap_destroy</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap)</td></tr>
+<tr class="memdesc:ga9f9c0844edb9717f4feacd79116b8e0d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a heap, freeing all its still allocated blocks.  <a href="group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d">More...</a><br /></td></tr>
+<tr class="separator:ga9f9c0844edb9717f4feacd79116b8e0d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gab8631ec88c8d26641b68b5d25dcd4422"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422">mi_heap_set_default</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap)</td></tr>
+<tr class="memdesc:gab8631ec88c8d26641b68b5d25dcd4422"><td class="mdescLeft">&#160;</td><td class="mdescRight">Set the default heap to use for <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> et al.  <a href="group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422">More...</a><br /></td></tr>
+<tr class="separator:gab8631ec88c8d26641b68b5d25dcd4422"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga8db4cbb87314a989a9a187464d6b5e05"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05">mi_heap_get_default</a> ()</td></tr>
+<tr class="memdesc:ga8db4cbb87314a989a9a187464d6b5e05"><td class="mdescLeft">&#160;</td><td class="mdescRight">Get the default heap that is used for <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> et al.  <a href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05">More...</a><br /></td></tr>
+<tr class="separator:ga8db4cbb87314a989a9a187464d6b5e05"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">mi_heap_get_backing</a> ()</td></tr>
+<tr class="memdesc:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Get the backing heap.  <a href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">More...</a><br /></td></tr>
+<tr class="separator:ga5d03fbe062ffcf38f0f417fd968357fc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7922f7495cde30b1984d0e6072419298"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">mi_heap_collect</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, bool force)</td></tr>
+<tr class="memdesc:ga7922f7495cde30b1984d0e6072419298"><td class="mdescLeft">&#160;</td><td class="mdescRight">Release outstanding resources in a specific heap.  <a href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">More...</a><br /></td></tr>
+<tr class="separator:ga7922f7495cde30b1984d0e6072419298"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga9cbed01e42c0647907295de92c3fa296"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">mi_heap_malloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
+<tr class="memdesc:ga9cbed01e42c0647907295de92c3fa296"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate in a specific heap.  <a href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">More...</a><br /></td></tr>
+<tr class="separator:ga9cbed01e42c0647907295de92c3fa296"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">mi_heap_malloc_small</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
+<tr class="memdesc:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a small object in a specific heap.  <a href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">More...</a><br /></td></tr>
+<tr class="separator:gaa1a1c7a1f4da6826b5a25b70ef878368"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga903104592c8ed53417a3762da6241133"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga903104592c8ed53417a3762da6241133">mi_heap_zalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size)</td></tr>
+<tr class="memdesc:ga903104592c8ed53417a3762da6241133"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate zero-initialized in a specific heap.  <a href="group__heap.html#ga903104592c8ed53417a3762da6241133">More...</a><br /></td></tr>
+<tr class="separator:ga903104592c8ed53417a3762da6241133"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaa6702b3c48e9e53e50e81b36f5011d55"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55">mi_heap_calloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t count, size_t size)</td></tr>
+<tr class="memdesc:gaa6702b3c48e9e53e50e81b36f5011d55"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> zero-initialized elements in a specific heap.  <a href="group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55">More...</a><br /></td></tr>
+<tr class="separator:gaa6702b3c48e9e53e50e81b36f5011d55"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga851da6c43fe0b71c1376cee8aef90db0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0">mi_heap_mallocn</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga851da6c43fe0b71c1376cee8aef90db0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> elements in a specific heap.  <a href="group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0">More...</a><br /></td></tr>
+<tr class="separator:ga851da6c43fe0b71c1376cee8aef90db0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga139d6b09dbf50c3c2523d0f4d1cfdeb5"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">mi_heap_strdup</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const char *s)</td></tr>
+<tr class="memdesc:ga139d6b09dbf50c3c2523d0f4d1cfdeb5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Duplicate a string in a specific heap.  <a href="group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">More...</a><br /></td></tr>
+<tr class="separator:ga139d6b09dbf50c3c2523d0f4d1cfdeb5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga8e3dbd46650dd26573cf307a2c8f1f5a"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a">mi_heap_strndup</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const char *s, size_t n)</td></tr>
+<tr class="memdesc:ga8e3dbd46650dd26573cf307a2c8f1f5a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Duplicate a string of at most length <em>n</em> in a specific heap.  <a href="group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a">More...</a><br /></td></tr>
+<tr class="separator:ga8e3dbd46650dd26573cf307a2c8f1f5a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga00e95ba1e01acac3cfd95bb7a357a6f0"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0">mi_heap_realpath</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, const char *fname, char *resolved_name)</td></tr>
+<tr class="memdesc:ga00e95ba1e01acac3cfd95bb7a357a6f0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Resolve a file path name using a specific <em>heap</em> to allocate the result.  <a href="group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0">More...</a><br /></td></tr>
+<tr class="separator:ga00e95ba1e01acac3cfd95bb7a357a6f0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaaef3395f66be48f37bdc8322509c5d81"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaaef3395f66be48f37bdc8322509c5d81">mi_heap_realloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize)</td></tr>
+<tr class="separator:gaaef3395f66be48f37bdc8322509c5d81"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gac74e94ad9b0c9b57c1c4d88b8825b7a8"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8">mi_heap_reallocn</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t count, size_t size)</td></tr>
+<tr class="separator:gac74e94ad9b0c9b57c1c4d88b8825b7a8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4a21070eb4e7cce018133c8d5f4b0527"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527">mi_heap_reallocf</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize)</td></tr>
+<tr class="separator:ga4a21070eb4e7cce018133c8d5f4b0527"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gab5b87e1805306f70df38789fcfcf6653"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gab5b87e1805306f70df38789fcfcf6653">mi_heap_malloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size, size_t alignment)</td></tr>
+<tr class="separator:gab5b87e1805306f70df38789fcfcf6653"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga23acd7680fb0976dde3783254c6c874b"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga23acd7680fb0976dde3783254c6c874b">mi_heap_malloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga23acd7680fb0976dde3783254c6c874b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaa450a59c6c7ae5fdbd1c2b80a8329ef0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0">mi_heap_zalloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size, size_t alignment)</td></tr>
+<tr class="separator:gaa450a59c6c7ae5fdbd1c2b80a8329ef0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga45fb43a62776fbebbdf1edd99b527954"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga45fb43a62776fbebbdf1edd99b527954">mi_heap_zalloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga45fb43a62776fbebbdf1edd99b527954"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4af03a6e2b93fae77424d93f889705c3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga4af03a6e2b93fae77424d93f889705c3">mi_heap_calloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t count, size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga4af03a6e2b93fae77424d93f889705c3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga08ca6419a5c057a4d965868998eef487"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#ga08ca6419a5c057a4d965868998eef487">mi_heap_calloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, size_t count, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga08ca6419a5c057a4d965868998eef487"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gafc603b696bd14cae6da28658f950d98c"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gafc603b696bd14cae6da28658f950d98c">mi_heap_realloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment)</td></tr>
+<tr class="separator:gafc603b696bd14cae6da28658f950d98c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf96c788a1bf553fe2d371de9365e047c"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__heap.html#gaf96c788a1bf553fe2d371de9365e047c">mi_heap_realloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:gaf96c788a1bf553fe2d371de9365e047c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>First-class heaps that can be destroyed in one go. </p>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga34a47cde5a5b38c29f1aa3c5e76943c2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga34a47cde5a5b38c29f1aa3c5e76943c2">&#9670;&nbsp;</a></span>mi_heap_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct mi_heap_s <a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Type of first-class heaps. </p>
+<p>A heap can only be used for (re)allocation in the thread that created this heap! Any allocated blocks can be freed by any other thread though. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gaa6702b3c48e9e53e50e81b36f5011d55"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa6702b3c48e9e53e50e81b36f5011d55">&#9670;&nbsp;</a></span>mi_heap_calloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_calloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> zero-initialized elements in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d" title="Allocate zero-initialized count elements of size bytes.">mi_calloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga4af03a6e2b93fae77424d93f889705c3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4af03a6e2b93fae77424d93f889705c3">&#9670;&nbsp;</a></span>mi_heap_calloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_calloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga08ca6419a5c057a4d965868998eef487"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga08ca6419a5c057a4d965868998eef487">&#9670;&nbsp;</a></span>mi_heap_calloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_calloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga7922f7495cde30b1984d0e6072419298"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7922f7495cde30b1984d0e6072419298">&#9670;&nbsp;</a></span>mi_heap_collect()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_heap_collect </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>force</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Release outstanding resources in a specific heap. </p>
+
+</div>
+</div>
+<a id="ga2ab1af8d438819b55319c7ef51d1e409"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga2ab1af8d438819b55319c7ef51d1e409">&#9670;&nbsp;</a></span>mi_heap_delete()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_heap_delete </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Delete a previously allocated heap. </p>
+<p>This will release resources and migrate any still allocated blocks in this heap (efficienty) to the default heap.</p>
+<p>If <em>heap</em> is the default heap, the default heap is set to the backing heap. </p>
+
+</div>
+</div>
+<a id="ga9f9c0844edb9717f4feacd79116b8e0d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9f9c0844edb9717f4feacd79116b8e0d">&#9670;&nbsp;</a></span>mi_heap_destroy()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_heap_destroy </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Destroy a heap, freeing all its still allocated blocks. </p>
+<p>Use with care as this will free all blocks still allocated in the heap. However, this can be a very efficient way to free all heap memory in one go.</p>
+<p>If <em>heap</em> is the default heap, the default heap is set to the backing heap. </p>
+
+</div>
+</div>
+<a id="ga5d03fbe062ffcf38f0f417fd968357fc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5d03fbe062ffcf38f0f417fd968357fc">&#9670;&nbsp;</a></span>mi_heap_get_backing()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* mi_heap_get_backing </td>
+          <td>(</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Get the backing heap. </p>
+<p>The <em>backing</em> heap is the initial default heap for a thread and always available for allocations. It cannot be destroyed or deleted except by exiting the thread. </p>
+
+</div>
+</div>
+<a id="ga8db4cbb87314a989a9a187464d6b5e05"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8db4cbb87314a989a9a187464d6b5e05">&#9670;&nbsp;</a></span>mi_heap_get_default()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* mi_heap_get_default </td>
+          <td>(</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Get the default heap that is used for <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> et al. </p>
+<dl class="section return"><dt>Returns</dt><dd>The current default heap. </dd></dl>
+
+</div>
+</div>
+<a id="ga9cbed01e42c0647907295de92c3fa296"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9cbed01e42c0647907295de92c3fa296">&#9670;&nbsp;</a></span>mi_heap_malloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_malloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gab5b87e1805306f70df38789fcfcf6653"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab5b87e1805306f70df38789fcfcf6653">&#9670;&nbsp;</a></span>mi_heap_malloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_malloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga23acd7680fb0976dde3783254c6c874b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga23acd7680fb0976dde3783254c6c874b">&#9670;&nbsp;</a></span>mi_heap_malloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_malloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaa1a1c7a1f4da6826b5a25b70ef878368"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa1a1c7a1f4da6826b5a25b70ef878368">&#9670;&nbsp;</a></span>mi_heap_malloc_small()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_malloc_small </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a small object in a specific heap. </p>
+<p><em>size</em> must be smaller or equal to <a class="el" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305" title="Maximum size allowed for small allocations in mi_malloc_small and mi_zalloc_small (usually 128*sizeof...">MI_SMALL_SIZE_MAX()</a>. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga851da6c43fe0b71c1376cee8aef90db0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga851da6c43fe0b71c1376cee8aef90db0">&#9670;&nbsp;</a></span>mi_heap_mallocn()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_mallocn </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> elements in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6" title="Allocate count elements of size bytes.">mi_mallocn()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga766f672ba56f2fbfeb9d9dbb0b7f6b11"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">&#9670;&nbsp;</a></span>mi_heap_new()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* mi_heap_new </td>
+          <td>(</td>
+          <td class="paramname"></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Create a new heap that can be used for allocation. </p>
+
+</div>
+</div>
+<a id="gaaef3395f66be48f37bdc8322509c5d81"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaaef3395f66be48f37bdc8322509c5d81">&#9670;&nbsp;</a></span>mi_heap_realloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_realloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gafc603b696bd14cae6da28658f950d98c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafc603b696bd14cae6da28658f950d98c">&#9670;&nbsp;</a></span>mi_heap_realloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_realloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaf96c788a1bf553fe2d371de9365e047c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf96c788a1bf553fe2d371de9365e047c">&#9670;&nbsp;</a></span>mi_heap_realloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_realloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga4a21070eb4e7cce018133c8d5f4b0527"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4a21070eb4e7cce018133c8d5f4b0527">&#9670;&nbsp;</a></span>mi_heap_reallocf()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_reallocf </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gac74e94ad9b0c9b57c1c4d88b8825b7a8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac74e94ad9b0c9b57c1c4d88b8825b7a8">&#9670;&nbsp;</a></span>mi_heap_reallocn()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_reallocn </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga00e95ba1e01acac3cfd95bb7a357a6f0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga00e95ba1e01acac3cfd95bb7a357a6f0">&#9670;&nbsp;</a></span>mi_heap_realpath()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_heap_realpath </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>fname</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">char *&#160;</td>
+          <td class="paramname"><em>resolved_name</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Resolve a file path name using a specific <em>heap</em> to allocate the result. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe" title="Resolve a file path name.">mi_realpath()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gab8631ec88c8d26641b68b5d25dcd4422"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab8631ec88c8d26641b68b5d25dcd4422">&#9670;&nbsp;</a></span>mi_heap_set_default()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* mi_heap_set_default </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Set the default heap to use for <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> et al. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">heap</td><td>The new default heap. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The previous default heap. </dd></dl>
+
+</div>
+</div>
+<a id="ga139d6b09dbf50c3c2523d0f4d1cfdeb5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">&#9670;&nbsp;</a></span>mi_heap_strdup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_heap_strdup </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>s</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Duplicate a string in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2" title="Allocate and duplicate a string.">mi_strdup()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga8e3dbd46650dd26573cf307a2c8f1f5a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8e3dbd46650dd26573cf307a2c8f1f5a">&#9670;&nbsp;</a></span>mi_heap_strndup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_heap_strndup </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>s</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>n</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Duplicate a string of at most length <em>n</em> in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#gaaabf971c2571891433477e2d21a35266" title="Allocate and duplicate a string up to n bytes.">mi_strndup()</a> </dd></dl>
+
+</div>
+</div>
+<a id="ga903104592c8ed53417a3762da6241133"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga903104592c8ed53417a3762da6241133">&#9670;&nbsp;</a></span>mi_heap_zalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_zalloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate zero-initialized in a specific heap. </p>
+<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000" title="Allocate zero-initialized size bytes.">mi_zalloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gaa450a59c6c7ae5fdbd1c2b80a8329ef0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa450a59c6c7ae5fdbd1c2b80a8329ef0">&#9670;&nbsp;</a></span>mi_heap_zalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_zalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga45fb43a62776fbebbdf1edd99b527954"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga45fb43a62776fbebbdf1edd99b527954">&#9670;&nbsp;</a></span>mi_heap_zalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_zalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__heap.js b/extlib/mimalloc/docs/group__heap.js
new file mode 100644 (file)
index 0000000..13d1377
--- /dev/null
@@ -0,0 +1,30 @@
+var group__heap =
+[
+    [ "mi_heap_t", "group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2", null ],
+    [ "mi_heap_calloc", "group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55", null ],
+    [ "mi_heap_calloc_aligned", "group__heap.html#ga4af03a6e2b93fae77424d93f889705c3", null ],
+    [ "mi_heap_calloc_aligned_at", "group__heap.html#ga08ca6419a5c057a4d965868998eef487", null ],
+    [ "mi_heap_collect", "group__heap.html#ga7922f7495cde30b1984d0e6072419298", null ],
+    [ "mi_heap_delete", "group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409", null ],
+    [ "mi_heap_destroy", "group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d", null ],
+    [ "mi_heap_get_backing", "group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc", null ],
+    [ "mi_heap_get_default", "group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05", null ],
+    [ "mi_heap_malloc", "group__heap.html#ga9cbed01e42c0647907295de92c3fa296", null ],
+    [ "mi_heap_malloc_aligned", "group__heap.html#gab5b87e1805306f70df38789fcfcf6653", null ],
+    [ "mi_heap_malloc_aligned_at", "group__heap.html#ga23acd7680fb0976dde3783254c6c874b", null ],
+    [ "mi_heap_malloc_small", "group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368", null ],
+    [ "mi_heap_mallocn", "group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0", null ],
+    [ "mi_heap_new", "group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11", null ],
+    [ "mi_heap_realloc", "group__heap.html#gaaef3395f66be48f37bdc8322509c5d81", null ],
+    [ "mi_heap_realloc_aligned", "group__heap.html#gafc603b696bd14cae6da28658f950d98c", null ],
+    [ "mi_heap_realloc_aligned_at", "group__heap.html#gaf96c788a1bf553fe2d371de9365e047c", null ],
+    [ "mi_heap_reallocf", "group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527", null ],
+    [ "mi_heap_reallocn", "group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8", null ],
+    [ "mi_heap_realpath", "group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0", null ],
+    [ "mi_heap_set_default", "group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422", null ],
+    [ "mi_heap_strdup", "group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5", null ],
+    [ "mi_heap_strndup", "group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a", null ],
+    [ "mi_heap_zalloc", "group__heap.html#ga903104592c8ed53417a3762da6241133", null ],
+    [ "mi_heap_zalloc_aligned", "group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0", null ],
+    [ "mi_heap_zalloc_aligned_at", "group__heap.html#ga45fb43a62776fbebbdf1edd99b527954", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__malloc.html b/extlib/mimalloc/docs/group__malloc.html
new file mode 100644 (file)
index 0000000..2dc1665
--- /dev/null
@@ -0,0 +1,638 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Basic Allocation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__malloc.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Basic Allocation</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>The basic allocation interface.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gaf2c7b89c327d1f60f59e68b9ea644d95"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95">mi_free</a> (void *p)</td></tr>
+<tr class="memdesc:gaf2c7b89c327d1f60f59e68b9ea644d95"><td class="mdescLeft">&#160;</td><td class="mdescRight">Free previously allocated memory.  <a href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95">More...</a><br /></td></tr>
+<tr class="separator:gaf2c7b89c327d1f60f59e68b9ea644d95"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3406e8b168bc74c8637b11571a6da83a"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a">mi_malloc</a> (size_t size)</td></tr>
+<tr class="memdesc:ga3406e8b168bc74c8637b11571a6da83a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>size</em> bytes.  <a href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a">More...</a><br /></td></tr>
+<tr class="separator:ga3406e8b168bc74c8637b11571a6da83a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gafdd9d8bb2986e668ba9884f28af38000"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000">mi_zalloc</a> (size_t size)</td></tr>
+<tr class="memdesc:gafdd9d8bb2986e668ba9884f28af38000"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate zero-initialized <code>size</code> bytes.  <a href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000">More...</a><br /></td></tr>
+<tr class="separator:gafdd9d8bb2986e668ba9884f28af38000"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga97fedb4f7107c592fd7f0f0a8949a57d"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d">mi_calloc</a> (size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga97fedb4f7107c592fd7f0f0a8949a57d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate zero-initialized <em>count</em> elements of <em>size</em> bytes.  <a href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d">More...</a><br /></td></tr>
+<tr class="separator:ga97fedb4f7107c592fd7f0f0a8949a57d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf11eb497da57bdfb2de65eb191c69db6"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6">mi_realloc</a> (void *p, size_t newsize)</td></tr>
+<tr class="memdesc:gaf11eb497da57bdfb2de65eb191c69db6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate memory to <em>newsize</em> bytes.  <a href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6">More...</a><br /></td></tr>
+<tr class="separator:gaf11eb497da57bdfb2de65eb191c69db6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga23a0fbb452b5dce8e31fab1a1958cacc"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">mi_recalloc</a> (void *p, size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga23a0fbb452b5dce8e31fab1a1958cacc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate memory to <em>count</em> elements of <em>size</em> bytes, with extra memory initialized to zero.  <a href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">More...</a><br /></td></tr>
+<tr class="separator:ga23a0fbb452b5dce8e31fab1a1958cacc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaaee66a1d483c3e28f585525fb96707e4"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4">mi_expand</a> (void *p, size_t newsize)</td></tr>
+<tr class="memdesc:gaaee66a1d483c3e28f585525fb96707e4"><td class="mdescLeft">&#160;</td><td class="mdescRight">Try to re-allocate memory to <em>newsize</em> bytes <em>in place</em>.  <a href="group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4">More...</a><br /></td></tr>
+<tr class="separator:gaaee66a1d483c3e28f585525fb96707e4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga0b05e2bf0f73e7401ae08597ff782ac6"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6">mi_mallocn</a> (size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga0b05e2bf0f73e7401ae08597ff782ac6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> elements of <em>size</em> bytes.  <a href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6">More...</a><br /></td></tr>
+<tr class="separator:ga0b05e2bf0f73e7401ae08597ff782ac6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga61d57b4144ba24fba5c1e9b956d13853"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853">mi_reallocn</a> (void *p, size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga61d57b4144ba24fba5c1e9b956d13853"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate memory to <em>count</em> elements of <em>size</em> bytes.  <a href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853">More...</a><br /></td></tr>
+<tr class="separator:ga61d57b4144ba24fba5c1e9b956d13853"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gafe68ac7c5e24a65cd55c9d6b152211a0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0">mi_reallocf</a> (void *p, size_t newsize)</td></tr>
+<tr class="memdesc:gafe68ac7c5e24a65cd55c9d6b152211a0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate memory to <em>newsize</em> bytes,.  <a href="group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0">More...</a><br /></td></tr>
+<tr class="separator:gafe68ac7c5e24a65cd55c9d6b152211a0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gac7cffe13f1f458ed16789488bf92b9b2"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2">mi_strdup</a> (const char *s)</td></tr>
+<tr class="memdesc:gac7cffe13f1f458ed16789488bf92b9b2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate and duplicate a string.  <a href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2">More...</a><br /></td></tr>
+<tr class="separator:gac7cffe13f1f458ed16789488bf92b9b2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaaabf971c2571891433477e2d21a35266"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#gaaabf971c2571891433477e2d21a35266">mi_strndup</a> (const char *s, size_t n)</td></tr>
+<tr class="memdesc:gaaabf971c2571891433477e2d21a35266"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate and duplicate a string up to <em>n</em> bytes.  <a href="group__malloc.html#gaaabf971c2571891433477e2d21a35266">More...</a><br /></td></tr>
+<tr class="separator:gaaabf971c2571891433477e2d21a35266"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga08cec32dd5bbe7da91c78d19f1b5bebe"><td class="memItemLeft" align="right" valign="top">char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe">mi_realpath</a> (const char *fname, char *resolved_name)</td></tr>
+<tr class="memdesc:ga08cec32dd5bbe7da91c78d19f1b5bebe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Resolve a file path name.  <a href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe">More...</a><br /></td></tr>
+<tr class="separator:ga08cec32dd5bbe7da91c78d19f1b5bebe"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>The basic allocation interface. </p>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga97fedb4f7107c592fd7f0f0a8949a57d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga97fedb4f7107c592fd7f0f0a8949a57d">&#9670;&nbsp;</a></span>mi_calloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_calloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate zero-initialized <em>count</em> elements of <em>size</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">count</td><td>number of elements. </td></tr>
+    <tr><td class="paramname">size</td><td>size of each element. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the allocated memory of <em>size*<em>count</em> bytes</em>, or <em>NULL</em> if either out of memory or when <code>count*size</code> overflows.</dd></dl>
+<p>Returns a unique pointer if called with either <em>size</em> or <em>count</em> of 0. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000" title="Allocate zero-initialized size bytes.">mi_zalloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gaaee66a1d483c3e28f585525fb96707e4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaaee66a1d483c3e28f585525fb96707e4">&#9670;&nbsp;</a></span>mi_expand()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_expand </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Try to re-allocate memory to <em>newsize</em> bytes <em>in place</em>. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>pointer to previously allocated memory (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">newsize</td><td>the new required size in bytes. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the re-allocated memory of <em>newsize</em> bytes (always equal to <em>p</em>), or <em>NULL</em> if either out of memory or if the memory could not be expanded in place. If <em>NULL</em> is returned, the pointer <em>p</em> is not freed. Otherwise the original pointer is returned as the reallocated result since it fits in-place with the new size. If <em>newsize</em> is larger than the original <em>size</em> allocated for <em>p</em>, the bytes after <em>size</em> are uninitialized. </dd></dl>
+
+</div>
+</div>
+<a id="gaf2c7b89c327d1f60f59e68b9ea644d95"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf2c7b89c327d1f60f59e68b9ea644d95">&#9670;&nbsp;</a></span>mi_free()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_free </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Free previously allocated memory. </p>
+<p>The pointer <code>p</code> must have been allocated before (or be <em>NULL</em>). </p><dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>pointer to free, or <em>NULL</em>. </td></tr>
+  </table>
+  </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga3406e8b168bc74c8637b11571a6da83a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3406e8b168bc74c8637b11571a6da83a">&#9670;&nbsp;</a></span>mi_malloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_malloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>size</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>number of bytes to allocate. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the allocated memory or <em>NULL</em> if out of memory. Returns a unique pointer if called with <em>size</em> 0. </dd></dl>
+
+</div>
+</div>
+<a id="ga0b05e2bf0f73e7401ae08597ff782ac6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0b05e2bf0f73e7401ae08597ff782ac6">&#9670;&nbsp;</a></span>mi_mallocn()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_mallocn </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> elements of <em>size</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">count</td><td>The number of elements. </td></tr>
+    <tr><td class="paramname">size</td><td>The size of each element. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>A pointer to a block of <em>count</em> * <em>size</em> bytes, or <em>NULL</em> if out of memory or if <em>count</em> * <em>size</em> overflows.</dd></dl>
+<p>If there is no overflow, it behaves exactly like <code>mi_malloc(p,count*size)</code>. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d" title="Allocate zero-initialized count elements of size bytes.">mi_calloc()</a> </dd>
+<dd>
+mi_zallocn() </dd></dl>
+
+</div>
+</div>
+<a id="gaf11eb497da57bdfb2de65eb191c69db6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf11eb497da57bdfb2de65eb191c69db6">&#9670;&nbsp;</a></span>mi_realloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_realloc </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate memory to <em>newsize</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>pointer to previously allocated memory (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">newsize</td><td>the new required size in bytes. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the re-allocated memory of <em>newsize</em> bytes, or <em>NULL</em> if out of memory. If <em>NULL</em> is returned, the pointer <em>p</em> is not freed. Otherwise the original pointer is either freed or returned as the reallocated result (in case it fits in-place with the new size). If the pointer <em>p</em> is <em>NULL</em>, it behaves as <em>mi_malloc</em>(<em>newsize</em>). If <em>newsize</em> is larger than the original <em>size</em> allocated for <em>p</em>, the bytes after <em>size</em> are uninitialized. </dd></dl>
+
+</div>
+</div>
+<a id="gafe68ac7c5e24a65cd55c9d6b152211a0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafe68ac7c5e24a65cd55c9d6b152211a0">&#9670;&nbsp;</a></span>mi_reallocf()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_reallocf </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate memory to <em>newsize</em> bytes,. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>pointer to previously allocated memory (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">newsize</td><td>the new required size in bytes. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>pointer to the re-allocated memory of <em>newsize</em> bytes, or <em>NULL</em> if out of memory.</dd></dl>
+<p>In contrast to <a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6" title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, if <em>NULL</em> is returned, the original pointer <em>p</em> is freed (if it was not <em>NULL</em> itself). Otherwise the original pointer is either freed or returned as the reallocated result (in case it fits in-place with the new size). If the pointer <em>p</em> is <em>NULL</em>, it behaves as <em>mi_malloc</em>(<em>newsize</em>). If <em>newsize</em> is larger than the original <em>size</em> allocated for <em>p</em>, the bytes after <em>size</em> are uninitialized.</p>
+<dl class="section see"><dt>See also</dt><dd><a href="https://www.freebsd.org/cgi/man.cgi?query=reallocf">reallocf</a> (on BSD) </dd></dl>
+
+</div>
+</div>
+<a id="ga61d57b4144ba24fba5c1e9b956d13853"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga61d57b4144ba24fba5c1e9b956d13853">&#9670;&nbsp;</a></span>mi_reallocn()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_reallocn </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate memory to <em>count</em> elements of <em>size</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>Pointer to a previously allocated block (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">count</td><td>The number of elements. </td></tr>
+    <tr><td class="paramname">size</td><td>The size of each element. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>A pointer to a re-allocated block of <em>count</em> * <em>size</em> bytes, or <em>NULL</em> if out of memory or if <em>count</em> * <em>size</em> overflows.</dd></dl>
+<p>If there is no overflow, it behaves exactly like <code>mi_realloc(p,count*size)</code>. </p><dl class="section see"><dt>See also</dt><dd><a href="http://man.openbsd.org/reallocarray">reallocarray()</a> (on BSD) </dd></dl>
+
+</div>
+</div>
+<a id="ga08cec32dd5bbe7da91c78d19f1b5bebe"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga08cec32dd5bbe7da91c78d19f1b5bebe">&#9670;&nbsp;</a></span>mi_realpath()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_realpath </td>
+          <td>(</td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>fname</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">char *&#160;</td>
+          <td class="paramname"><em>resolved_name</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Resolve a file path name. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">fname</td><td>File name. </td></tr>
+    <tr><td class="paramname">resolved_name</td><td>Should be <em>NULL</em> (but can also point to a buffer of at least <em>PATH_MAX</em> bytes). </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>If successful a pointer to the resolved absolute file name, or <em>NULL</em> on failure (with <em>errno</em> set to the error code).</dd></dl>
+<p>If <em>resolved_name</em> was <em>NULL</em>, the returned result should be freed with <a class="el" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95" title="Free previously allocated memory.">mi_free()</a>.</p>
+<p>Replacement for the standard <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html">realpath()</a> such that <a class="el" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95" title="Free previously allocated memory.">mi_free()</a> can be used on the returned result (if <em>resolved_name</em> was <em>NULL</em>). </p>
+
+</div>
+</div>
+<a id="ga23a0fbb452b5dce8e31fab1a1958cacc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga23a0fbb452b5dce8e31fab1a1958cacc">&#9670;&nbsp;</a></span>mi_recalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void * mi_recalloc </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate memory to <em>count</em> elements of <em>size</em> bytes, with extra memory initialized to zero. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">p</td><td>Pointer to a previously allocated block (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">count</td><td>The number of elements. </td></tr>
+    <tr><td class="paramname">size</td><td>The size of each element. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>A pointer to a re-allocated block of <em>count</em> * <em>size</em> bytes, or <em>NULL</em> if out of memory or if <em>count</em> * <em>size</em> overflows.</dd></dl>
+<p>If there is no overflow, it behaves exactly like <code>mi_rezalloc(p,count*size)</code>. </p><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853" title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a> </dd>
+<dd>
+<a href="http://man.openbsd.org/reallocarray">recallocarray()</a> (on BSD). </dd></dl>
+
+</div>
+</div>
+<a id="gac7cffe13f1f458ed16789488bf92b9b2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac7cffe13f1f458ed16789488bf92b9b2">&#9670;&nbsp;</a></span>mi_strdup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_strdup </td>
+          <td>(</td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>s</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate and duplicate a string. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">s</td><td>string to duplicate (or <em>NULL</em>). </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>a pointer to newly allocated memory initialized to string <em>s</em>, or <em>NULL</em> if either out of memory or if <em>s</em> is <em>NULL</em>.</dd></dl>
+<p>Replacement for the standard <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html">strdup()</a> such that <a class="el" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95" title="Free previously allocated memory.">mi_free()</a> can be used on the returned result. </p>
+
+</div>
+</div>
+<a id="gaaabf971c2571891433477e2d21a35266"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaaabf971c2571891433477e2d21a35266">&#9670;&nbsp;</a></span>mi_strndup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">char* mi_strndup </td>
+          <td>(</td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>s</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>n</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate and duplicate a string up to <em>n</em> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">s</td><td>string to duplicate (or <em>NULL</em>). </td></tr>
+    <tr><td class="paramname">n</td><td>maximum number of bytes to copy (excluding the terminating zero). </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>a pointer to newly allocated memory initialized to string <em>s</em> up to the first <em>n</em> bytes (and always zero terminated), or <em>NULL</em> if either out of memory or if <em>s</em> is <em>NULL</em>.</dd></dl>
+<p>Replacement for the standard <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html">strndup()</a> such that <a class="el" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95" title="Free previously allocated memory.">mi_free()</a> can be used on the returned result. </p>
+
+</div>
+</div>
+<a id="gafdd9d8bb2986e668ba9884f28af38000"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafdd9d8bb2986e668ba9884f28af38000">&#9670;&nbsp;</a></span>mi_zalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_zalloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate zero-initialized <code>size</code> bytes. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">size</td><td>The size in bytes. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>Pointer to newly allocated zero initialized memory, or <em>NULL</em> if out of memory. </dd></dl>
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__malloc.js b/extlib/mimalloc/docs/group__malloc.js
new file mode 100644 (file)
index 0000000..7293ffa
--- /dev/null
@@ -0,0 +1,16 @@
+var group__malloc =
+[
+    [ "mi_calloc", "group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d", null ],
+    [ "mi_expand", "group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4", null ],
+    [ "mi_free", "group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95", null ],
+    [ "mi_malloc", "group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a", null ],
+    [ "mi_mallocn", "group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6", null ],
+    [ "mi_realloc", "group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6", null ],
+    [ "mi_reallocf", "group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0", null ],
+    [ "mi_reallocn", "group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853", null ],
+    [ "mi_realpath", "group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe", null ],
+    [ "mi_recalloc", "group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc", null ],
+    [ "mi_strdup", "group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2", null ],
+    [ "mi_strndup", "group__malloc.html#gaaabf971c2571891433477e2d21a35266", null ],
+    [ "mi_zalloc", "group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__options.html b/extlib/mimalloc/docs/group__options.html
new file mode 100644 (file)
index 0000000..f92905d
--- /dev/null
@@ -0,0 +1,404 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Runtime Options</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__options.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#enum-members">Enumerations</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Runtime Options</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Set runtime behavior.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="enum-members"></a>
+Enumerations</h2></td></tr>
+<tr class="memitem:gafebf7ed116adb38ae5218bc3ce06884c"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> { <br />
+&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">mi_option_show_errors</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">mi_option_show_stats</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">mi_option_verbose</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">mi_option_eager_commit</a>
+, <br />
+&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">mi_option_eager_region_commit</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">mi_option_large_os_pages</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2">mi_option_reserve_huge_os_pages</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c">mi_option_reserve_huge_os_pages_at</a>
+, <br />
+&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5">mi_option_reset_delay</a>
+, <br />
+&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74">mi_option_use_numa_nodes</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a>
+, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a>
+, <br />
+&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a>
+<br />
+ }</td></tr>
+<tr class="memdesc:gafebf7ed116adb38ae5218bc3ce06884c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Runtime options.  <a href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">More...</a><br /></td></tr>
+<tr class="separator:gafebf7ed116adb38ae5218bc3ce06884c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga459ad98f18b3fc9275474807fe0ca188"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga459ad98f18b3fc9275474807fe0ca188">mi_option_is_enabled</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option)</td></tr>
+<tr class="separator:ga459ad98f18b3fc9275474807fe0ca188"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga04180ae41b0d601421dd62ced40ca050"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga04180ae41b0d601421dd62ced40ca050">mi_option_enable</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option)</td></tr>
+<tr class="separator:ga04180ae41b0d601421dd62ced40ca050"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaebf6ff707a2e688ebb1a2296ca564054"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#gaebf6ff707a2e688ebb1a2296ca564054">mi_option_disable</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option)</td></tr>
+<tr class="separator:gaebf6ff707a2e688ebb1a2296ca564054"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga9a13d05fcb77489cb06d4d017ebd8bed"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed">mi_option_set_enabled</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, bool enable)</td></tr>
+<tr class="separator:ga9a13d05fcb77489cb06d4d017ebd8bed"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga65518b69ec5d32336b50e07f74b3f629"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga65518b69ec5d32336b50e07f74b3f629">mi_option_set_enabled_default</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, bool enable)</td></tr>
+<tr class="separator:ga65518b69ec5d32336b50e07f74b3f629"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7e8af195cc81d3fa64ccf2662caa565a"><td class="memItemLeft" align="right" valign="top">long&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a">mi_option_get</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option)</td></tr>
+<tr class="separator:ga7e8af195cc81d3fa64ccf2662caa565a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf84921c32375e25754dc2ee6a911fa60"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#gaf84921c32375e25754dc2ee6a911fa60">mi_option_set</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, long value)</td></tr>
+<tr class="separator:gaf84921c32375e25754dc2ee6a911fa60"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7ef623e440e6e5545cb08c94e71e4b90"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90">mi_option_set_default</a> (<a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, long value)</td></tr>
+<tr class="separator:ga7ef623e440e6e5545cb08c94e71e4b90"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>Set runtime behavior. </p>
+<h2 class="groupheader">Enumeration Type Documentation</h2>
+<a id="gafebf7ed116adb38ae5218bc3ce06884c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafebf7ed116adb38ae5218bc3ce06884c">&#9670;&nbsp;</a></span>mi_option_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Runtime options. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0"></a>mi_option_show_errors&#160;</td><td class="fielddoc"><p>Print error messages to <code>stderr</code>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda"></a>mi_option_show_stats&#160;</td><td class="fielddoc"><p>Print statistics to <code>stderr</code> when the program is done. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777"></a>mi_option_verbose&#160;</td><td class="fielddoc"><p>Print verbose messages to <code>stderr</code>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b"></a>mi_option_eager_commit&#160;</td><td class="fielddoc"><p>Eagerly commit segments (4MiB) (enabled by default). </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad"></a>mi_option_eager_region_commit&#160;</td><td class="fielddoc"><p>Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows) </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e"></a>mi_option_large_os_pages&#160;</td><td class="fielddoc"><p>Use large OS pages (2MiB in size) if possible. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2"></a>mi_option_reserve_huge_os_pages&#160;</td><td class="fielddoc"><p>The number of huge OS pages (1GiB in size) to reserve at the start of the program. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c"></a>mi_option_reserve_huge_os_pages_at&#160;</td><td class="fielddoc"><p>Reserve huge OS pages at node N. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1"></a>mi_option_segment_cache&#160;</td><td class="fielddoc"><p>The number of segments per thread to keep cached. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"></a>mi_option_page_reset&#160;</td><td class="fielddoc"><p>Reset page memory after <em>mi_option_reset_delay</em> milliseconds when it becomes free. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d"></a>mi_option_segment_reset&#160;</td><td class="fielddoc"><p>Experimental. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5"></a>mi_option_reset_delay&#160;</td><td class="fielddoc"><p>Delay in milli-seconds before resetting a page (100ms by default) </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74"></a>mi_option_use_numa_nodes&#160;</td><td class="fielddoc"><p>Pretend there are at most N NUMA nodes. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"></a>mi_option_reset_decommits&#160;</td><td class="fielddoc"><p>Experimental. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c"></a>mi_option_eager_commit_delay&#160;</td><td class="fielddoc"><p>Experimental. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf"></a>mi_option_os_tag&#160;</td><td class="fielddoc"><p>OS tag to assign to mimalloc'd memory. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"></a>_mi_option_last&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gaebf6ff707a2e688ebb1a2296ca564054"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaebf6ff707a2e688ebb1a2296ca564054">&#9670;&nbsp;</a></span>mi_option_disable()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_disable </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga04180ae41b0d601421dd62ced40ca050"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga04180ae41b0d601421dd62ced40ca050">&#9670;&nbsp;</a></span>mi_option_enable()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_enable </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga7e8af195cc81d3fa64ccf2662caa565a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7e8af195cc81d3fa64ccf2662caa565a">&#9670;&nbsp;</a></span>mi_option_get()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">long mi_option_get </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga459ad98f18b3fc9275474807fe0ca188"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga459ad98f18b3fc9275474807fe0ca188">&#9670;&nbsp;</a></span>mi_option_is_enabled()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">bool mi_option_is_enabled </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaf84921c32375e25754dc2ee6a911fa60"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf84921c32375e25754dc2ee6a911fa60">&#9670;&nbsp;</a></span>mi_option_set()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_set </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">long&#160;</td>
+          <td class="paramname"><em>value</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga7ef623e440e6e5545cb08c94e71e4b90"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7ef623e440e6e5545cb08c94e71e4b90">&#9670;&nbsp;</a></span>mi_option_set_default()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_set_default </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">long&#160;</td>
+          <td class="paramname"><em>value</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga9a13d05fcb77489cb06d4d017ebd8bed"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9a13d05fcb77489cb06d4d017ebd8bed">&#9670;&nbsp;</a></span>mi_option_set_enabled()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_set_enabled </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>enable</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga65518b69ec5d32336b50e07f74b3f629"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga65518b69ec5d32336b50e07f74b3f629">&#9670;&nbsp;</a></span>mi_option_set_enabled_default()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_option_set_enabled_default </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>&#160;</td>
+          <td class="paramname"><em>option</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">bool&#160;</td>
+          <td class="paramname"><em>enable</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__options.js b/extlib/mimalloc/docs/group__options.js
new file mode 100644 (file)
index 0000000..c8836cd
--- /dev/null
@@ -0,0 +1,30 @@
+var group__options =
+[
+    [ "mi_option_t", "group__options.html#gafebf7ed116adb38ae5218bc3ce06884c", [
+      [ "mi_option_show_errors", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0", null ],
+      [ "mi_option_show_stats", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda", null ],
+      [ "mi_option_verbose", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777", null ],
+      [ "mi_option_eager_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b", null ],
+      [ "mi_option_eager_region_commit", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad", null ],
+      [ "mi_option_large_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e", null ],
+      [ "mi_option_reserve_huge_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2", null ],
+      [ "mi_option_reserve_huge_os_pages_at", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c", null ],
+      [ "mi_option_segment_cache", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1", null ],
+      [ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ],
+      [ "mi_option_segment_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d", null ],
+      [ "mi_option_reset_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5", null ],
+      [ "mi_option_use_numa_nodes", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74", null ],
+      [ "mi_option_reset_decommits", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536", null ],
+      [ "mi_option_eager_commit_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c", null ],
+      [ "mi_option_os_tag", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf", null ],
+      [ "_mi_option_last", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a", null ]
+    ] ],
+    [ "mi_option_disable", "group__options.html#gaebf6ff707a2e688ebb1a2296ca564054", null ],
+    [ "mi_option_enable", "group__options.html#ga04180ae41b0d601421dd62ced40ca050", null ],
+    [ "mi_option_get", "group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a", null ],
+    [ "mi_option_is_enabled", "group__options.html#ga459ad98f18b3fc9275474807fe0ca188", null ],
+    [ "mi_option_set", "group__options.html#gaf84921c32375e25754dc2ee6a911fa60", null ],
+    [ "mi_option_set_default", "group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90", null ],
+    [ "mi_option_set_enabled", "group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed", null ],
+    [ "mi_option_set_enabled_default", "group__options.html#ga65518b69ec5d32336b50e07f74b3f629", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__posix.html b/extlib/mimalloc/docs/group__posix.html
new file mode 100644 (file)
index 0000000..539f7ec
--- /dev/null
@@ -0,0 +1,532 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Posix</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__posix.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Posix</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga4531c9e775bb3ae12db57c1ba8a5d7de"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de">mi_malloc_size</a> (const void *p)</td></tr>
+<tr class="separator:ga4531c9e775bb3ae12db57c1ba8a5d7de"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">mi_malloc_usable_size</a> (const void *p)</td></tr>
+<tr class="separator:ga06d07cf357bbac5c73ba5d0c0c421e17"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">mi_cfree</a> (void *p)</td></tr>
+<tr class="memdesc:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Just as <code>free</code> but also checks if the pointer <code>p</code> belongs to our heap.  <a href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">More...</a><br /></td></tr>
+<tr class="separator:ga705dc7a64bffacfeeb0141501a5c35d7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gacff84f226ba9feb2031b8992e5579447"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">mi_posix_memalign</a> (void **p, size_t alignment, size_t size)</td></tr>
+<tr class="separator:gacff84f226ba9feb2031b8992e5579447"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gad5a69c8fea96aa2b7a7c818c2130090a"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a">mi__posix_memalign</a> (void **p, size_t alignment, size_t size)</td></tr>
+<tr class="separator:gad5a69c8fea96aa2b7a7c818c2130090a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaab7fa71ea93b96873f5d9883db57d40e"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e">mi_memalign</a> (size_t alignment, size_t size)</td></tr>
+<tr class="separator:gaab7fa71ea93b96873f5d9883db57d40e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga73baaf5951f5165ba0763d0c06b6a93b"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b">mi_valloc</a> (size_t size)</td></tr>
+<tr class="separator:ga73baaf5951f5165ba0763d0c06b6a93b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaeb325c39b887d3b90d85d1eb1712fb1e"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e">mi_pvalloc</a> (size_t size)</td></tr>
+<tr class="separator:gaeb325c39b887d3b90d85d1eb1712fb1e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga1326d2e4388630b5f81ca7206318b8e5"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5">mi_aligned_alloc</a> (size_t alignment, size_t size)</td></tr>
+<tr class="separator:ga1326d2e4388630b5f81ca7206318b8e5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga48fad8648a2f1dab9c87ea9448a52088"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088">mi_reallocarray</a> (void *p, size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga48fad8648a2f1dab9c87ea9448a52088"><td class="mdescLeft">&#160;</td><td class="mdescRight">Correspond s to <a href="https://www.freebsd.org/cgi/man.cgi?query=reallocarray&amp;sektion=3&amp;manpath=freebsd-release-ports">reallocarray</a> in FreeBSD.  <a href="group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088">More...</a><br /></td></tr>
+<tr class="separator:ga48fad8648a2f1dab9c87ea9448a52088"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga7e1934d60a3e697950eeb48e042bfad5"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5">mi_reallocarr</a> (void *p, size_t count, size_t size)</td></tr>
+<tr class="memdesc:ga7e1934d60a3e697950eeb48e042bfad5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Corresponds to <a href="https://man.netbsd.org/reallocarr.3">reallocarr</a> in NetBSD.  <a href="group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5">More...</a><br /></td></tr>
+<tr class="separator:ga7e1934d60a3e697950eeb48e042bfad5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae01389eedab8d67341ff52e2aad80ebb"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gae01389eedab8d67341ff52e2aad80ebb">mi_free_size</a> (void *p, size_t size)</td></tr>
+<tr class="separator:gae01389eedab8d67341ff52e2aad80ebb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga72e9d7ffb5fe94d69bc722c8506e27bc"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc">mi_free_size_aligned</a> (void *p, size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga72e9d7ffb5fe94d69bc722c8506e27bc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">mi_free_aligned</a> (void *p, size_t alignment)</td></tr>
+<tr class="separator:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions. </p>
+<p>Defined for convenience as all redirect to the regular mimalloc API. </p>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gad5a69c8fea96aa2b7a7c818c2130090a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad5a69c8fea96aa2b7a7c818c2130090a">&#9670;&nbsp;</a></span>mi__posix_memalign()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi__posix_memalign </td>
+          <td>(</td>
+          <td class="paramtype">void **&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga1326d2e4388630b5f81ca7206318b8e5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1326d2e4388630b5f81ca7206318b8e5">&#9670;&nbsp;</a></span>mi_aligned_alloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_aligned_alloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga705dc7a64bffacfeeb0141501a5c35d7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga705dc7a64bffacfeeb0141501a5c35d7">&#9670;&nbsp;</a></span>mi_cfree()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_cfree </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Just as <code>free</code> but also checks if the pointer <code>p</code> belongs to our heap. </p>
+
+</div>
+</div>
+<a id="ga0d28d5cf61e6bfbb18c63092939fe5c9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0d28d5cf61e6bfbb18c63092939fe5c9">&#9670;&nbsp;</a></span>mi_free_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_free_aligned </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gae01389eedab8d67341ff52e2aad80ebb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae01389eedab8d67341ff52e2aad80ebb">&#9670;&nbsp;</a></span>mi_free_size()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_free_size </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga72e9d7ffb5fe94d69bc722c8506e27bc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga72e9d7ffb5fe94d69bc722c8506e27bc">&#9670;&nbsp;</a></span>mi_free_size_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void mi_free_size_aligned </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga4531c9e775bb3ae12db57c1ba8a5d7de"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4531c9e775bb3ae12db57c1ba8a5d7de">&#9670;&nbsp;</a></span>mi_malloc_size()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t mi_malloc_size </td>
+          <td>(</td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga06d07cf357bbac5c73ba5d0c0c421e17"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga06d07cf357bbac5c73ba5d0c0c421e17">&#9670;&nbsp;</a></span>mi_malloc_usable_size()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t mi_malloc_usable_size </td>
+          <td>(</td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>p</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaab7fa71ea93b96873f5d9883db57d40e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaab7fa71ea93b96873f5d9883db57d40e">&#9670;&nbsp;</a></span>mi_memalign()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_memalign </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gacff84f226ba9feb2031b8992e5579447"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacff84f226ba9feb2031b8992e5579447">&#9670;&nbsp;</a></span>mi_posix_memalign()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi_posix_memalign </td>
+          <td>(</td>
+          <td class="paramtype">void **&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gaeb325c39b887d3b90d85d1eb1712fb1e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaeb325c39b887d3b90d85d1eb1712fb1e">&#9670;&nbsp;</a></span>mi_pvalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_pvalloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga7e1934d60a3e697950eeb48e042bfad5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7e1934d60a3e697950eeb48e042bfad5">&#9670;&nbsp;</a></span>mi_reallocarr()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">int mi_reallocarr </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Corresponds to <a href="https://man.netbsd.org/reallocarr.3">reallocarr</a> in NetBSD. </p>
+
+</div>
+</div>
+<a id="ga48fad8648a2f1dab9c87ea9448a52088"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga48fad8648a2f1dab9c87ea9448a52088">&#9670;&nbsp;</a></span>mi_reallocarray()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_reallocarray </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>count</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Correspond s to <a href="https://www.freebsd.org/cgi/man.cgi?query=reallocarray&amp;sektion=3&amp;manpath=freebsd-release-ports">reallocarray</a> in FreeBSD. </p>
+
+</div>
+</div>
+<a id="ga73baaf5951f5165ba0763d0c06b6a93b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga73baaf5951f5165ba0763d0c06b6a93b">&#9670;&nbsp;</a></span>mi_valloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_valloc </td>
+          <td>(</td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__posix.js b/extlib/mimalloc/docs/group__posix.js
new file mode 100644 (file)
index 0000000..50c248c
--- /dev/null
@@ -0,0 +1,17 @@
+var group__posix =
+[
+    [ "mi__posix_memalign", "group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a", null ],
+    [ "mi_aligned_alloc", "group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5", null ],
+    [ "mi_cfree", "group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7", null ],
+    [ "mi_free_aligned", "group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9", null ],
+    [ "mi_free_size", "group__posix.html#gae01389eedab8d67341ff52e2aad80ebb", null ],
+    [ "mi_free_size_aligned", "group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc", null ],
+    [ "mi_malloc_size", "group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de", null ],
+    [ "mi_malloc_usable_size", "group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17", null ],
+    [ "mi_memalign", "group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e", null ],
+    [ "mi_posix_memalign", "group__posix.html#gacff84f226ba9feb2031b8992e5579447", null ],
+    [ "mi_pvalloc", "group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e", null ],
+    [ "mi_reallocarr", "group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5", null ],
+    [ "mi_reallocarray", "group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088", null ],
+    [ "mi_valloc", "group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__typed.html b/extlib/mimalloc/docs/group__typed.html
new file mode 100644 (file)
index 0000000..c19c7f4
--- /dev/null
@@ -0,0 +1,518 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Typed Macros</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__typed.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#define-members">Macros</a>  </div>
+  <div class="headertitle">
+<div class="title">Typed Macros</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Typed allocation macros.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga0619a62c5fd886f1016030abe91f0557"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">mi_malloc_tp</a>(tp)</td></tr>
+<tr class="memdesc:ga0619a62c5fd886f1016030abe91f0557"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a block of type <em>tp</em>.  <a href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">More...</a><br /></td></tr>
+<tr class="separator:ga0619a62c5fd886f1016030abe91f0557"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gac77a61bdaf680a803785fe307820b48c"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gac77a61bdaf680a803785fe307820b48c">mi_zalloc_tp</a>(tp)</td></tr>
+<tr class="memdesc:gac77a61bdaf680a803785fe307820b48c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a zero-initialized block of type <em>tp</em>.  <a href="group__typed.html#gac77a61bdaf680a803785fe307820b48c">More...</a><br /></td></tr>
+<tr class="separator:gac77a61bdaf680a803785fe307820b48c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae80c47c9d4cab10961fff1a8ac98fc07"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07">mi_calloc_tp</a>(tp,  count)</td></tr>
+<tr class="memdesc:gae80c47c9d4cab10961fff1a8ac98fc07"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> zero-initialized blocks of type <em>tp</em>.  <a href="group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07">More...</a><br /></td></tr>
+<tr class="separator:gae80c47c9d4cab10961fff1a8ac98fc07"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae5cb6e0fafc9f23169c5622e077afe8b"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b">mi_mallocn_tp</a>(tp,  count)</td></tr>
+<tr class="memdesc:gae5cb6e0fafc9f23169c5622e077afe8b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> blocks of type <em>tp</em>.  <a href="group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b">More...</a><br /></td></tr>
+<tr class="separator:gae5cb6e0fafc9f23169c5622e077afe8b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga1158b49a55dfa81f58a4426a7578f523"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga1158b49a55dfa81f58a4426a7578f523">mi_reallocn_tp</a>(p,  tp,  count)</td></tr>
+<tr class="memdesc:ga1158b49a55dfa81f58a4426a7578f523"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate to <em>count</em> blocks of type <em>tp</em>.  <a href="group__typed.html#ga1158b49a55dfa81f58a4426a7578f523">More...</a><br /></td></tr>
+<tr class="separator:ga1158b49a55dfa81f58a4426a7578f523"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga653bcb24ac495bc19940ecd6898f9cd7"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7">mi_heap_malloc_tp</a>(hp,  tp)</td></tr>
+<tr class="memdesc:ga653bcb24ac495bc19940ecd6898f9cd7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a block of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7">More...</a><br /></td></tr>
+<tr class="separator:ga653bcb24ac495bc19940ecd6898f9cd7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gad6e87e86e994aa14416ae9b5d4c188fe"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe">mi_heap_zalloc_tp</a>(hp,  tp)</td></tr>
+<tr class="memdesc:gad6e87e86e994aa14416ae9b5d4c188fe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate a zero-initialized block of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe">More...</a><br /></td></tr>
+<tr class="separator:gad6e87e86e994aa14416ae9b5d4c188fe"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4e5d1f1707c90e5f55e023ac5f45fe74"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74">mi_heap_calloc_tp</a>(hp,  tp,  count)</td></tr>
+<tr class="memdesc:ga4e5d1f1707c90e5f55e023ac5f45fe74"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> zero-initialized blocks of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74">More...</a><br /></td></tr>
+<tr class="separator:ga4e5d1f1707c90e5f55e023ac5f45fe74"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga6b75cb9c4b9c647661d0924552dc6e83"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83">mi_heap_mallocn_tp</a>(hp,  tp,  count)</td></tr>
+<tr class="memdesc:ga6b75cb9c4b9c647661d0924552dc6e83"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83">More...</a><br /></td></tr>
+<tr class="separator:ga6b75cb9c4b9c647661d0924552dc6e83"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gaf213d5422ec35e7f6caad827c79bc948"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#gaf213d5422ec35e7f6caad827c79bc948">mi_heap_reallocn_tp</a>(hp,  p,  tp,  count)</td></tr>
+<tr class="memdesc:gaf213d5422ec35e7f6caad827c79bc948"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#gaf213d5422ec35e7f6caad827c79bc948">More...</a><br /></td></tr>
+<tr class="separator:gaf213d5422ec35e7f6caad827c79bc948"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e">mi_heap_recalloc_tp</a>(hp,  p,  tp,  count)</td></tr>
+<tr class="memdesc:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Re-allocate to <em>count</em> zero initialized blocks of type <em>tp</em> in a heap <em>hp</em>.  <a href="group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e">More...</a><br /></td></tr>
+<tr class="separator:ga3e50a1600958fcaf1a7f3560c9174f9e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>Typed allocation macros. </p>
+<p>For example: </p><div class="fragment"><div class="line"><span class="keywordtype">int</span>* p = <a class="code" href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">mi_malloc_tp</a>(<span class="keywordtype">int</span>)</div>
+<div class="ttc" id="agroup__typed_html_ga0619a62c5fd886f1016030abe91f0557"><div class="ttname"><a href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">mi_malloc_tp</a></div><div class="ttdeci">#define mi_malloc_tp(tp)</div><div class="ttdoc">Allocate a block of type tp.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:692</div></div>
+</div><!-- fragment --> <h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="gae80c47c9d4cab10961fff1a8ac98fc07"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae80c47c9d4cab10961fff1a8ac98fc07">&#9670;&nbsp;</a></span>mi_calloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_calloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> zero-initialized blocks of type <em>tp</em>. </p>
+
+</div>
+</div>
+<a id="ga4e5d1f1707c90e5f55e023ac5f45fe74"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4e5d1f1707c90e5f55e023ac5f45fe74">&#9670;&nbsp;</a></span>mi_heap_calloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_calloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> zero-initialized blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="ga653bcb24ac495bc19940ecd6898f9cd7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga653bcb24ac495bc19940ecd6898f9cd7">&#9670;&nbsp;</a></span>mi_heap_malloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_malloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a block of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="ga6b75cb9c4b9c647661d0924552dc6e83"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga6b75cb9c4b9c647661d0924552dc6e83">&#9670;&nbsp;</a></span>mi_heap_mallocn_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_mallocn_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="gaf213d5422ec35e7f6caad827c79bc948"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf213d5422ec35e7f6caad827c79bc948">&#9670;&nbsp;</a></span>mi_heap_reallocn_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_reallocn_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">p, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate to <em>count</em> blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="ga3e50a1600958fcaf1a7f3560c9174f9e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3e50a1600958fcaf1a7f3560c9174f9e">&#9670;&nbsp;</a></span>mi_heap_recalloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_recalloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">p, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate to <em>count</em> zero initialized blocks of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="gad6e87e86e994aa14416ae9b5d4c188fe"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad6e87e86e994aa14416ae9b5d4c188fe">&#9670;&nbsp;</a></span>mi_heap_zalloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_heap_zalloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">hp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a zero-initialized block of type <em>tp</em> in a heap <em>hp</em>. </p>
+
+</div>
+</div>
+<a id="ga0619a62c5fd886f1016030abe91f0557"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0619a62c5fd886f1016030abe91f0557">&#9670;&nbsp;</a></span>mi_malloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_malloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp</td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a block of type <em>tp</em>. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">tp</td><td>The type of the block to allocate. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>A pointer to an object of type <em>tp</em>, or <em>NULL</em> if out of memory.</dd></dl>
+<p><b>Example:</b> </p><div class="fragment"><div class="line"><span class="keywordtype">int</span>* p = <a class="code" href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">mi_malloc_tp</a>(<span class="keywordtype">int</span>)</div>
+</div><!-- fragment --><dl class="section see"><dt>See also</dt><dd><a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a> </dd></dl>
+
+</div>
+</div>
+<a id="gae5cb6e0fafc9f23169c5622e077afe8b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae5cb6e0fafc9f23169c5622e077afe8b">&#9670;&nbsp;</a></span>mi_mallocn_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_mallocn_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate <em>count</em> blocks of type <em>tp</em>. </p>
+
+</div>
+</div>
+<a id="ga1158b49a55dfa81f58a4426a7578f523"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1158b49a55dfa81f58a4426a7578f523">&#9670;&nbsp;</a></span>mi_reallocn_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_reallocn_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">p, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">count&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Re-allocate to <em>count</em> blocks of type <em>tp</em>. </p>
+
+</div>
+</div>
+<a id="gac77a61bdaf680a803785fe307820b48c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac77a61bdaf680a803785fe307820b48c">&#9670;&nbsp;</a></span>mi_zalloc_tp</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define mi_zalloc_tp</td>
+          <td>(</td>
+          <td class="paramtype">&#160;</td>
+          <td class="paramname">tp</td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocate a zero-initialized block of type <em>tp</em>. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__typed.js b/extlib/mimalloc/docs/group__typed.js
new file mode 100644 (file)
index 0000000..c6be55d
--- /dev/null
@@ -0,0 +1,14 @@
+var group__typed =
+[
+    [ "mi_calloc_tp", "group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07", null ],
+    [ "mi_heap_calloc_tp", "group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74", null ],
+    [ "mi_heap_malloc_tp", "group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7", null ],
+    [ "mi_heap_mallocn_tp", "group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83", null ],
+    [ "mi_heap_reallocn_tp", "group__typed.html#gaf213d5422ec35e7f6caad827c79bc948", null ],
+    [ "mi_heap_recalloc_tp", "group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e", null ],
+    [ "mi_heap_zalloc_tp", "group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe", null ],
+    [ "mi_malloc_tp", "group__typed.html#ga0619a62c5fd886f1016030abe91f0557", null ],
+    [ "mi_mallocn_tp", "group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b", null ],
+    [ "mi_reallocn_tp", "group__typed.html#ga1158b49a55dfa81f58a4426a7578f523", null ],
+    [ "mi_zalloc_tp", "group__typed.html#gac77a61bdaf680a803785fe307820b48c", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/group__zeroinit.html b/extlib/mimalloc/docs/group__zeroinit.html
new file mode 100644 (file)
index 0000000..329a773
--- /dev/null
@@ -0,0 +1,591 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Zero initialized re-allocation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('group__zeroinit.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="summary">
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">Zero initialized re-allocation</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too.  
+<a href="#details">More...</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga8c292e142110229a2980b37ab036dbc6"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6">mi_rezalloc</a> (void *p, size_t newsize)</td></tr>
+<tr class="separator:ga8c292e142110229a2980b37ab036dbc6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gacd71a7bce96aab38ae6de17af2eb2cf0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0">mi_rezalloc_aligned</a> (void *p, size_t newsize, size_t alignment)</td></tr>
+<tr class="separator:gacd71a7bce96aab38ae6de17af2eb2cf0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gae8b358c417e61d5307da002702b0a8e1"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1">mi_rezalloc_aligned_at</a> (void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:gae8b358c417e61d5307da002702b0a8e1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga3e7e5c291acf1c7fd7ffd9914a9f945f"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f">mi_recalloc_aligned</a> (void *p, size_t newcount, size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga3e7e5c291acf1c7fd7ffd9914a9f945f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga4ff5e92ad73585418a072c9d059e5cf9"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9">mi_recalloc_aligned_at</a> (void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga4ff5e92ad73585418a072c9d059e5cf9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gacfad83f14eb5d6a42a497a898e19fc76"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76">mi_heap_rezalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize)</td></tr>
+<tr class="separator:gacfad83f14eb5d6a42a497a898e19fc76"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga8648c5fbb22a80f0262859099f06dfbd"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd">mi_heap_recalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size)</td></tr>
+<tr class="separator:ga8648c5fbb22a80f0262859099f06dfbd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga375fa8a611c51905e592d5d467c49664"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664">mi_heap_rezalloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment)</td></tr>
+<tr class="separator:ga375fa8a611c51905e592d5d467c49664"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:gac90da54fa7e5d10bdc97ce0b51dce2eb"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb">mi_heap_rezalloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:gac90da54fa7e5d10bdc97ce0b51dce2eb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga9f3f999396c8f77ca5e80e7b40ac29e3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3">mi_heap_recalloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size, size_t alignment)</td></tr>
+<tr class="separator:ga9f3f999396c8f77ca5e80e7b40ac29e3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ga496452c96f1de8c500be9fddf52edaf7"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7">mi_heap_recalloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</td></tr>
+<tr class="separator:ga496452c96f1de8c500be9fddf52edaf7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<p>The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too. </p>
+<p>e.g. <code>mi_calloc</code>, <code>mi_zalloc</code>, <code>mi_zalloc_aligned</code> etc. see <a href="https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992">https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992</a> </p>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga8648c5fbb22a80f0262859099f06dfbd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8648c5fbb22a80f0262859099f06dfbd">&#9670;&nbsp;</a></span>mi_heap_recalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_recalloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga9f3f999396c8f77ca5e80e7b40ac29e3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9f3f999396c8f77ca5e80e7b40ac29e3">&#9670;&nbsp;</a></span>mi_heap_recalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_recalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga496452c96f1de8c500be9fddf52edaf7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga496452c96f1de8c500be9fddf52edaf7">&#9670;&nbsp;</a></span>mi_heap_recalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_recalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gacfad83f14eb5d6a42a497a898e19fc76"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacfad83f14eb5d6a42a497a898e19fc76">&#9670;&nbsp;</a></span>mi_heap_rezalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_rezalloc </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga375fa8a611c51905e592d5d467c49664"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga375fa8a611c51905e592d5d467c49664">&#9670;&nbsp;</a></span>mi_heap_rezalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_rezalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gac90da54fa7e5d10bdc97ce0b51dce2eb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac90da54fa7e5d10bdc97ce0b51dce2eb">&#9670;&nbsp;</a></span>mi_heap_rezalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_heap_rezalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
+          <td class="paramname"><em>heap</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga3e7e5c291acf1c7fd7ffd9914a9f945f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3e7e5c291acf1c7fd7ffd9914a9f945f">&#9670;&nbsp;</a></span>mi_recalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_recalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga4ff5e92ad73585418a072c9d059e5cf9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4ff5e92ad73585418a072c9d059e5cf9">&#9670;&nbsp;</a></span>mi_recalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_recalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newcount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>size</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ga8c292e142110229a2980b37ab036dbc6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8c292e142110229a2980b37ab036dbc6">&#9670;&nbsp;</a></span>mi_rezalloc()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_rezalloc </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gacd71a7bce96aab38ae6de17af2eb2cf0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacd71a7bce96aab38ae6de17af2eb2cf0">&#9670;&nbsp;</a></span>mi_rezalloc_aligned()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_rezalloc_aligned </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="gae8b358c417e61d5307da002702b0a8e1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae8b358c417e61d5307da002702b0a8e1">&#9670;&nbsp;</a></span>mi_rezalloc_aligned_at()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* mi_rezalloc_aligned_at </td>
+          <td>(</td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>p</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>newsize</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>alignment</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>offset</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/group__zeroinit.js b/extlib/mimalloc/docs/group__zeroinit.js
new file mode 100644 (file)
index 0000000..b9297d2
--- /dev/null
@@ -0,0 +1,14 @@
+var group__zeroinit =
+[
+    [ "mi_heap_recalloc", "group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd", null ],
+    [ "mi_heap_recalloc_aligned", "group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3", null ],
+    [ "mi_heap_recalloc_aligned_at", "group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7", null ],
+    [ "mi_heap_rezalloc", "group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76", null ],
+    [ "mi_heap_rezalloc_aligned", "group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664", null ],
+    [ "mi_heap_rezalloc_aligned_at", "group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb", null ],
+    [ "mi_recalloc_aligned", "group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f", null ],
+    [ "mi_recalloc_aligned_at", "group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9", null ],
+    [ "mi_rezalloc", "group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6", null ],
+    [ "mi_rezalloc_aligned", "group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0", null ],
+    [ "mi_rezalloc_aligned_at", "group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1", null ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/index.html b/extlib/mimalloc/docs/index.html
new file mode 100644 (file)
index 0000000..2ea9121
--- /dev/null
@@ -0,0 +1,142 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Main Page</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('index.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">mi-malloc Documentation</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>This is the API documentation of the <a href="https://github.com/microsoft/mimalloc">mimalloc</a> allocator (pronounced "me-malloc") &ndash; a general purpose allocator with excellent <a href="bench.html">performance</a> characteristics. Initially developed by Daan Leijen for the run-time systems of the <a href="https://github.com/koka-lang/koka">Koka</a> and <a href="https://github.com/leanprover/lean">Lean</a> languages.</p>
+<p>It is a drop-in replacement for <code>malloc</code> and can be used in other programs without code changes, for example, on Unix you can use it as: </p><div class="fragment"><div class="line">&gt; LD_PRELOAD=/usr/bin/libmimalloc.so  myprogram</div>
+</div><!-- fragment --><p>Notable aspects of the design include:</p>
+<ul>
+<li><b>small and consistent</b>: the library is about 8k LOC using simple and consistent data structures. This makes it very suitable to integrate and adapt in other projects. For runtime systems it provides hooks for a monotonic <em>heartbeat</em> and deferred freeing (for bounded worst-case times with reference counting).</li>
+<li><b>free list sharding</b>: instead of one big free list (per size class) we have many smaller lists per "mimalloc page" which reduces fragmentation and increases locality &ndash; things that are allocated close in time get allocated close in memory. (A mimalloc page contains blocks of one size class and is usually 64KiB on a 64-bit system).</li>
+<li><b>free list multi-sharding</b>: the big idea! Not only do we shard the free list per mimalloc page, but for each page we have multiple free lists. In particular, there is one list for thread-local <code>free</code> operations, and another one for concurrent <code>free</code> operations. Free-ing from another thread can now be a single CAS without needing sophisticated coordination between threads. Since there will be thousands of separate free lists, contention is naturally distributed over the heap, and the chance of contending on a single location will be low &ndash; this is quite similar to randomized algorithms like skip lists where adding a random oracle removes the need for a more complex algorithm.</li>
+<li><b>eager page reset</b>: when a "page" becomes empty (with increased chance due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged") reducing (real) memory pressure and fragmentation, especially in long running programs.</li>
+<li><b>secure</b>: <em>mimalloc</em> can be build in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. The performance penalty is only around 5% on average over our benchmarks.</li>
+<li><b>first-class heaps</b>: efficiently create and use multiple heaps to allocate across different regions. A heap can be destroyed at once instead of deallocating each object separately.</li>
+<li><b>bounded</b>: it does not suffer from <em>blowup</em> [1], has bounded worst-case allocation times (<em>wcat</em>), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes), and has no internal points of contention using only atomic operations.</li>
+<li><b>fast</b>: In our benchmarks (see <a href="#performance">below</a>), <em>mimalloc</em> outperforms all other leading allocators (<em>jemalloc</em>, <em>tcmalloc</em>, <em>Hoard</em>, etc), and usually uses less memory (up to 25% more in the worst case). A nice property is that it does consistently well over a wide range of benchmarks.</li>
+</ul>
+<p>You can read more on the design of <em>mimalloc</em> in the <a href="https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action">technical report</a> which also has detailed benchmark results.</p>
+<p>Further information:</p>
+<ul>
+<li><a class="el" href="build.html">Building</a></li>
+<li><a class="el" href="using.html">Using the library</a></li>
+<li><a class="el" href="environment.html">Environment Options</a></li>
+<li><a class="el" href="overrides.html">Overriding Malloc</a></li>
+<li><a class="el" href="bench.html">Performance</a></li>
+<li><a class="el" href="group__malloc.html">Basic Allocation</a></li>
+<li><a class="el" href="group__extended.html">Extended Functions</a></li>
+<li><a class="el" href="group__aligned.html">Aligned Allocation</a></li>
+<li><a class="el" href="group__heap.html">Heap Allocation</a></li>
+<li><a class="el" href="group__typed.html">Typed Macros</a></li>
+<li><a class="el" href="group__analysis.html">Heap Introspection</a></li>
+<li><a class="el" href="group__options.html">Runtime Options</a></li>
+<li><a class="el" href="group__posix.html">Posix</a></li>
+<li><a class="el" href="group__cpp.html">C++ wrappers</a> </li>
+</ul>
+</div></div><!-- PageDoc -->
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/jquery.js b/extlib/mimalloc/docs/jquery.js
new file mode 100644 (file)
index 0000000..103c32d
--- /dev/null
@@ -0,0 +1,35 @@
+/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
+/*! jQuery UI - v1.12.1 - 2019-01-27
+* http://jqueryui.com
+* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/resizable.js, widgets/mouse.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}t.ui=t.ui||{},t.ui.version="1.12.1";var i=0,s=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var l=h+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,n,o=s.call(arguments,1),a=0,r=o.length;r>a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),h=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):h=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,o="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:o?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType,o=!s&&!n;return{element:i,isWindow:s,isDocument:n,offset:o?t(e).offset():{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:i.outerWidth(),height:i.outerHeight()}}},t.fn.position=function(n){if(!n||!n.of)return d.apply(this,arguments);n=t.extend({},n);var u,p,f,m,g,_,v=t(n.of),b=t.position.getWithinInfo(n.within),y=t.position.getScrollInfo(b),w=(n.collision||"flip").split(" "),x={};return _=s(v),v[0].preventDefault&&(n.at="left top"),p=_.width,f=_.height,m=_.offset,g=t.extend({},m),t.each(["my","at"],function(){var t,e,i=(n[this]||"").split(" ");1===i.length&&(i=r.test(i[0])?i.concat(["center"]):h.test(i[0])?["center"].concat(i):["center","center"]),i[0]=r.test(i[0])?i[0]:"center",i[1]=h.test(i[1])?i[1]:"center",t=l.exec(i[0]),e=l.exec(i[1]),x[this]=[t?t[0]:0,e?e[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===n.at[0]?g.left+=p:"center"===n.at[0]&&(g.left+=p/2),"bottom"===n.at[1]?g.top+=f:"center"===n.at[1]&&(g.top+=f/2),u=e(x.at,p,f),g.left+=u[0],g.top+=u[1],this.each(function(){var s,r,h=t(this),l=h.outerWidth(),c=h.outerHeight(),d=i(this,"marginLeft"),_=i(this,"marginTop"),k=l+d+i(this,"marginRight")+y.width,C=c+_+i(this,"marginBottom")+y.height,D=t.extend({},g),T=e(x.my,h.outerWidth(),h.outerHeight());"right"===n.my[0]?D.left-=l:"center"===n.my[0]&&(D.left-=l/2),"bottom"===n.my[1]?D.top-=c:"center"===n.my[1]&&(D.top-=c/2),D.left+=T[0],D.top+=T[1],s={marginLeft:d,marginTop:_},t.each(["left","top"],function(e,i){t.ui.position[w[e]]&&t.ui.position[w[e]][i](D,{targetWidth:p,targetHeight:f,elemWidth:l,elemHeight:c,collisionPosition:s,collisionWidth:k,collisionHeight:C,offset:[u[0]+T[0],u[1]+T[1]],my:n.my,at:n.at,within:b,elem:h})}),n.using&&(r=function(t){var e=m.left-D.left,i=e+p-l,s=m.top-D.top,r=s+f-c,u={target:{element:v,left:m.left,top:m.top,width:p,height:f},element:{element:h,left:D.left,top:D.top,width:l,height:c},horizontal:0>i?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,(i>0||u>a(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var n=!1;t(document).on("mouseup",function(){n=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("<div>"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element
+},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),m&&(p-=l),g&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable});/**
+ * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 2.1.2
+ */
+;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1<b.axis.length;u&&(d/=2);b.offset=h(b.offset);b.over=h(b.over);return this.each(function(){function k(a){var k=$.extend({},b,{queue:!0,duration:d,complete:a&&function(){a.call(q,e,b)}});r.animate(f,k)}if(null!==a){var l=n(this),q=l?this.contentWindow||window:this,r=$(q),e=a,f={},t;switch(typeof e){case "number":case "string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(e)){e= h(e);break}e=l?$(e):$(e,q);case "object":if(e.length===0)return;if(e.is||e.style)t=(e=$(e)).offset()}var v=$.isFunction(b.offset)&&b.offset(q,e)||b.offset;$.each(b.axis.split(""),function(a,c){var d="x"===c?"Left":"Top",m=d.toLowerCase(),g="scroll"+d,h=r[g](),n=p.max(q,c);t?(f[g]=t[m]+(l?0:h-r.offset()[m]),b.margin&&(f[g]-=parseInt(e.css("margin"+d),10)||0,f[g]-=parseInt(e.css("border"+d+"Width"),10)||0),f[g]+=v[m]||0,b.over[m]&&(f[g]+=e["x"===c?"width":"height"]()*b.over[m])):(d=e[m],f[g]=d.slice&& "%"===d.slice(-1)?parseFloat(d)/100*n:d);b.limit&&/^\d+$/.test(f[g])&&(f[g]=0>=f[g]?0:Math.min(f[g],n));!a&&1<b.axis.length&&(h===f[g]?f={}:u&&(k(b.onAfterFirst),f={}))});k(b.onAfter)}})};p.max=function(a,d){var b="x"===d?"Width":"Height",h="scroll"+b;if(!n(a))return a[h]-$(a)[b.toLowerCase()]();var b="client"+b,k=a.ownerDocument||a.document,l=k.documentElement,k=k.body;return Math.max(l[h],k[h])-Math.min(l[b],k[b])};$.Tween.propHooks.scrollLeft=$.Tween.propHooks.scrollTop={get:function(a){return $(a.elem)[a.prop]()}, set:function(a){var d=this.get(a);if(a.options.interrupt&&a._last&&a._last!==d)return $(a.elem).stop();var b=Math.round(a.now);d!==b&&($(a.elem)[a.prop](b),a._last=this.get(a))}};return p});
+/*!
+ PowerTip v1.3.1 (2018-04-15)
+ https://stevenbenner.github.io/jquery-powertip/
+ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory(require("jquery"))}else{factory(root.jQuery)}})(this,function($){var $document=$(document),$window=$(window),$body=$("body");var DATA_DISPLAYCONTROLLER="displayController",DATA_HASACTIVEHOVER="hasActiveHover",DATA_FORCEDOPEN="forcedOpen",DATA_HASMOUSEMOVE="hasMouseMove",DATA_MOUSEONTOTIP="mouseOnToPopup",DATA_ORIGINALTITLE="originalTitle",DATA_POWERTIP="powertip",DATA_POWERTIPJQ="powertipjq",DATA_POWERTIPTARGET="powertiptarget",EVENT_NAMESPACE=".powertip",RAD2DEG=180/Math.PI,MOUSE_EVENTS=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"];var session={tooltips:null,isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var Collision={none:0,top:1,bottom:2,left:4,right:8};$.fn.powerTip=function(opts,arg){var targetElements=this,options,tipController;if(!targetElements.length){return targetElements}if($.type(opts)==="string"&&$.powerTip[opts]){return $.powerTip[opts].call(targetElements,targetElements,arg)}options=$.extend({},$.fn.powerTip.defaults,opts);tipController=new TooltipController(options);initTracking();targetElements.each(function elementSetup(){var $this=$(this),dataPowertip=$this.data(DATA_POWERTIP),dataElem=$this.data(DATA_POWERTIPJQ),dataTarget=$this.data(DATA_POWERTIPTARGET),title=$this.attr("title");if(!dataPowertip&&!dataTarget&&!dataElem&&title){$this.data(DATA_POWERTIP,title);$this.data(DATA_ORIGINALTITLE,title);$this.removeAttr("title")}$this.data(DATA_DISPLAYCONTROLLER,new DisplayController($this,options,tipController))});if(!options.manual){$.each(options.openEvents,function(idx,evt){if($.inArray(evt,options.closeEvents)>-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference<options.intentSensitivity){cancelClose();closeAnyDelayed();tipController.showTip(element)}else{session.previousX=session.currentX;session.previousY=session.currentY;openTooltip()}}function cancelTimer(stopClose){hoverTimer=clearTimeout(hoverTimer);if(session.closeDelayTimeout&&myCloseDelay===session.closeDelayTimeout||stopClose){cancelClose()}}function cancelClose(){session.closeDelayTimeout=clearTimeout(session.closeDelayTimeout);session.delayInProgress=false}function closeAnyDelayed(){if(session.delayInProgress&&session.activeHover&&!session.activeHover.is(element)){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true)}}function repositionTooltip(){tipController.resetPosition(element)}this.show=openTooltip;this.hide=closeTooltip;this.cancel=cancelTimer;this.resetPosition=repositionTooltip}function PlacementCalculator(){function computePlacementCoords(element,placement,tipWidth,tipHeight,offset){var placementBase=placement.split("-")[0],coords=new CSSCoordinates,position;if(isSvgElement(element)){position=getSvgPlacement(element,placementBase)}else{position=getHtmlPlacement(element,placementBase)}switch(placement){case"n":coords.set("left",position.left-tipWidth/2);coords.set("bottom",session.windowHeight-position.top+offset);break;case"e":coords.set("left",position.left+offset);coords.set("top",position.top-tipHeight/2);break;case"s":coords.set("left",position.left-tipWidth/2);coords.set("top",position.top+offset);break;case"w":coords.set("top",position.top-tipHeight/2);coords.set("right",session.windowWidth-position.left+offset);break;case"nw":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"nw-alt":coords.set("left",position.left);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne":coords.set("left",position.left-20);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne-alt":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left);break;case"sw":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"sw-alt":coords.set("left",position.left);coords.set("top",position.top+offset);break;case"se":coords.set("left",position.left-20);coords.set("top",position.top+offset);break;case"se-alt":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left);break}return coords}function getHtmlPlacement(element,placement){var objectOffset=element.offset(),objectWidth=element.outerWidth(),objectHeight=element.outerHeight(),left,top;switch(placement){case"n":left=objectOffset.left+objectWidth/2;top=objectOffset.top;break;case"e":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight/2;break;case"s":left=objectOffset.left+objectWidth/2;top=objectOffset.top+objectHeight;break;case"w":left=objectOffset.left;top=objectOffset.top+objectHeight/2;break;case"nw":left=objectOffset.left;top=objectOffset.top;break;case"ne":left=objectOffset.left+objectWidth;top=objectOffset.top;break;case"sw":left=objectOffset.left;top=objectOffset.top+objectHeight;break;case"se":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight;break}return{top:top,left:left}}function getSvgPlacement(element,placement){var svgElement=element.closest("svg")[0],domElement=element[0],point=svgElement.createSVGPoint(),boundingBox=domElement.getBBox(),matrix=domElement.getScreenCTM(),halfWidth=boundingBox.width/2,halfHeight=boundingBox.height/2,placements=[],placementKeys=["nw","n","ne","e","se","s","sw","w"],coords,rotation,steps,x;function pushPlacement(){placements.push(point.matrixTransform(matrix))}point.x=boundingBox.x;point.y=boundingBox.y;pushPlacement();point.x+=halfWidth;pushPlacement();point.x+=halfWidth;pushPlacement();point.y+=halfHeight;pushPlacement();point.y+=halfHeight;pushPlacement();point.x-=halfWidth;pushPlacement();point.x-=halfWidth;pushPlacement();point.y-=halfHeight;pushPlacement();if(placements[0].y!==placements[1].y||placements[0].x!==placements[7].x){rotation=Math.atan2(matrix.b,matrix.a)*RAD2DEG;steps=Math.ceil((rotation%360-22.5)/45);if(steps<1){steps+=8}while(steps--){placementKeys.push(placementKeys.shift())}}for(x=0;x<placements.length;x++){if(placementKeys[x]===placement){coords=placements[x];break}}return{top:coords.y+session.scrollTop,left:coords.x+session.scrollLeft}}this.compute=computePlacementCoords}function TooltipController(options){var placementCalculator=new PlacementCalculator,tipElement=$("#"+options.popupId);if(tipElement.length===0){tipElement=$("<div/>",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.top<viewportTop||Math.abs(coords.bottom-session.windowHeight)-elementHeight<viewportTop){collisions|=Collision.top}if(coords.top+elementHeight>viewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.left<viewportLeft||coords.right+elementWidth>viewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right<viewportLeft){collisions|=Collision.right}return collisions}function countFlags(value){var count=0;while(value){value&=value-1;count++}return count}return $.powerTip});/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ *  jquery.ui.widget.js
+ *  jquery.ui.mouse.js
+ */
+!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017
+ * http://www.smartmenus.org/
+ * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy(this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("<span/>").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('<div class="sm-jquery-disable-overlay"/>').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0],$('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y<o.upEnd)&&a.eq(o.up?1:0).show(),o.y==n)mouse&&a.eq(o.up?0:1).hide(),this.menuScrollStop(t);else if(!e){this.opts.scrollAccelerate&&o.step<this.opts.scrollStep&&(o.step+=.2);var h=this;this.scrollTimeout=requestAnimationFrame(function(){h.menuScroll(t)})}},menuScrollMousewheel:function(t,e){if(this.getClosestMenu(e.target)==t[0]){e=e.originalEvent;var i=(e.wheelDelta||-e.detail)>0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0),canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$});
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/mimalloc-doc_8h_source.html b/extlib/mimalloc/docs/mimalloc-doc_8h_source.html
new file mode 100644 (file)
index 0000000..8935de8
--- /dev/null
@@ -0,0 +1,561 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: mimalloc-doc.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('mimalloc-doc_8h_source.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">mimalloc-doc.h</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;<span class="comment">/* ----------------------------------------------------------------------------</span></div>
+<div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;<span class="comment">Copyright (c) 2018-2021, Microsoft Research, Daan Leijen</span></div>
+<div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;<span class="comment">This is free software; you can redistribute it and/or modify it under the</span></div>
+<div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;<span class="comment">terms of the MIT license. A copy of the license can be found in the file</span></div>
+<div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160;<span class="comment">&quot;LICENSE&quot; at the root of this distribution.</span></div>
+<div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160;<span class="comment">-----------------------------------------------------------------------------*/</span></div>
+<div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160; </div>
+<div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;<span class="preprocessor">#error &quot;documentation file only!&quot;</span></div>
+<div class="line"><a name="l00009"></a><span class="lineno">    9</span>&#160; </div>
+<div class="line"><a name="l00010"></a><span class="lineno">   10</span>&#160; </div>
+<div class="line"><a name="l00094"></a><span class="lineno">   94</span>&#160; </div>
+<div class="line"><a name="l00095"></a><span class="lineno">   95</span>&#160; </div>
+<div class="line"><a name="l00099"></a><span class="lineno"><a class="line" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95">   99</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95">mi_free</a>(<span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00100"></a><span class="lineno">  100</span>&#160; </div>
+<div class="line"><a name="l00105"></a><span class="lineno"><a class="line" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a">  105</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a">mi_malloc</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00106"></a><span class="lineno">  106</span>&#160; </div>
+<div class="line"><a name="l00111"></a><span class="lineno"><a class="line" href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000">  111</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000">mi_zalloc</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00112"></a><span class="lineno">  112</span>&#160; </div>
+<div class="line"><a name="l00122"></a><span class="lineno"><a class="line" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d">  122</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d">mi_calloc</a>(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00123"></a><span class="lineno">  123</span>&#160; </div>
+<div class="line"><a name="l00136"></a><span class="lineno"><a class="line" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6">  136</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6">mi_realloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00137"></a><span class="lineno">  137</span>&#160; </div>
+<div class="line"><a name="l00148"></a><span class="lineno"><a class="line" href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">  148</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">mi_recalloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00149"></a><span class="lineno">  149</span>&#160; </div>
+<div class="line"><a name="l00163"></a><span class="lineno"><a class="line" href="group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4">  163</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4">mi_expand</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00164"></a><span class="lineno">  164</span>&#160; </div>
+<div class="line"><a name="l00174"></a><span class="lineno"><a class="line" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6">  174</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6">mi_mallocn</a>(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00175"></a><span class="lineno">  175</span>&#160; </div>
+<div class="line"><a name="l00185"></a><span class="lineno"><a class="line" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853">  185</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853">mi_reallocn</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00186"></a><span class="lineno">  186</span>&#160; </div>
+<div class="line"><a name="l00203"></a><span class="lineno"><a class="line" href="group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0">  203</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0">mi_reallocf</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00204"></a><span class="lineno">  204</span>&#160; </div>
+<div class="line"><a name="l00205"></a><span class="lineno">  205</span>&#160; </div>
+<div class="line"><a name="l00214"></a><span class="lineno"><a class="line" href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2">  214</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2">mi_strdup</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* s);</div>
+<div class="line"><a name="l00215"></a><span class="lineno">  215</span>&#160; </div>
+<div class="line"><a name="l00225"></a><span class="lineno"><a class="line" href="group__malloc.html#gaaabf971c2571891433477e2d21a35266">  225</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__malloc.html#gaaabf971c2571891433477e2d21a35266">mi_strndup</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* s, <span class="keywordtype">size_t</span> n);</div>
+<div class="line"><a name="l00226"></a><span class="lineno">  226</span>&#160; </div>
+<div class="line"><a name="l00239"></a><span class="lineno"><a class="line" href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe">  239</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe">mi_realpath</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">char</span>* resolved_name);</div>
+<div class="line"><a name="l00240"></a><span class="lineno">  240</span>&#160; </div>
+<div class="line"><a name="l00242"></a><span class="lineno">  242</span>&#160; </div>
+<div class="line"><a name="l00243"></a><span class="lineno">  243</span>&#160;<span class="comment">// ------------------------------------------------------</span></div>
+<div class="line"><a name="l00244"></a><span class="lineno">  244</span>&#160;<span class="comment">// Extended functionality</span></div>
+<div class="line"><a name="l00245"></a><span class="lineno">  245</span>&#160;<span class="comment">// ------------------------------------------------------</span></div>
+<div class="line"><a name="l00246"></a><span class="lineno">  246</span>&#160; </div>
+<div class="line"><a name="l00250"></a><span class="lineno">  250</span>&#160; </div>
+<div class="line"><a name="l00253"></a><span class="lineno"><a class="line" href="group__extended.html#ga1ea64283508718d9d645c38efc2f4305">  253</a></span>&#160;<span class="preprocessor">#define MI_SMALL_SIZE_MAX   (128*sizeof(void*))</span></div>
+<div class="line"><a name="l00254"></a><span class="lineno">  254</span>&#160; </div>
+<div class="line"><a name="l00262"></a><span class="lineno"><a class="line" href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99">  262</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99">mi_malloc_small</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00263"></a><span class="lineno">  263</span>&#160; </div>
+<div class="line"><a name="l00271"></a><span class="lineno"><a class="line" href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152">  271</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152">mi_zalloc_small</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00272"></a><span class="lineno">  272</span>&#160; </div>
+<div class="line"><a name="l00287"></a><span class="lineno"><a class="line" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee">  287</a></span>&#160;<span class="keywordtype">size_t</span> <a class="code" href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee">mi_usable_size</a>(<span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00288"></a><span class="lineno">  288</span>&#160; </div>
+<div class="line"><a name="l00298"></a><span class="lineno"><a class="line" href="group__extended.html#gac057927cd06c854b45fe7847e921bd47">  298</a></span>&#160;<span class="keywordtype">size_t</span> <a class="code" href="group__extended.html#gac057927cd06c854b45fe7847e921bd47">mi_good_size</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00299"></a><span class="lineno">  299</span>&#160; </div>
+<div class="line"><a name="l00307"></a><span class="lineno"><a class="line" href="group__extended.html#ga421430e2226d7d468529cec457396756">  307</a></span>&#160;<span class="keywordtype">void</span>   <a class="code" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a>(<span class="keywordtype">bool</span> force);</div>
+<div class="line"><a name="l00308"></a><span class="lineno">  308</span>&#160; </div>
+<div class="line"><a name="l00313"></a><span class="lineno"><a class="line" href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">  313</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">mi_stats_print</a>(<span class="keywordtype">void</span>* out);</div>
+<div class="line"><a name="l00314"></a><span class="lineno">  314</span>&#160; </div>
+<div class="line"><a name="l00320"></a><span class="lineno"><a class="line" href="group__extended.html#ga537f13b299ddf801e49a5a94fde02c79">  320</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga537f13b299ddf801e49a5a94fde02c79">mi_stats_print_out</a>(<a class="code" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>* out, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00321"></a><span class="lineno">  321</span>&#160; </div>
+<div class="line"><a name="l00323"></a><span class="lineno"><a class="line" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">  323</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a>(<span class="keywordtype">void</span>);</div>
+<div class="line"><a name="l00324"></a><span class="lineno">  324</span>&#160; </div>
+<div class="line"><a name="l00326"></a><span class="lineno"><a class="line" href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">  326</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">mi_stats_merge</a>(<span class="keywordtype">void</span>);</div>
+<div class="line"><a name="l00327"></a><span class="lineno">  327</span>&#160; </div>
+<div class="line"><a name="l00331"></a><span class="lineno"><a class="line" href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">  331</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">mi_thread_init</a>(<span class="keywordtype">void</span>);</div>
+<div class="line"><a name="l00332"></a><span class="lineno">  332</span>&#160; </div>
+<div class="line"><a name="l00337"></a><span class="lineno"><a class="line" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">  337</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a>(<span class="keywordtype">void</span>);</div>
+<div class="line"><a name="l00338"></a><span class="lineno">  338</span>&#160; </div>
+<div class="line"><a name="l00344"></a><span class="lineno"><a class="line" href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">  344</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">mi_thread_stats_print_out</a>(<a class="code" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>* out, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00345"></a><span class="lineno">  345</span>&#160; </div>
+<div class="line"><a name="l00352"></a><span class="lineno"><a class="line" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">  352</a></span>&#160;<span class="keyword">typedef</span> void (<a class="code" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a>)(<span class="keywordtype">bool</span> force, <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span> heartbeat, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00353"></a><span class="lineno">  353</span>&#160; </div>
+<div class="line"><a name="l00369"></a><span class="lineno"><a class="line" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">  369</a></span>&#160;<span class="keywordtype">void</span>   <a class="code" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">mi_register_deferred_free</a>(<a class="code" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a>* deferred_free, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00370"></a><span class="lineno">  370</span>&#160; </div>
+<div class="line"><a name="l00376"></a><span class="lineno"><a class="line" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">  376</a></span>&#160;<span class="keyword">typedef</span> void (<a class="code" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>)(<span class="keyword">const</span> <span class="keywordtype">char</span>* msg, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00377"></a><span class="lineno">  377</span>&#160; </div>
+<div class="line"><a name="l00384"></a><span class="lineno"><a class="line" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">  384</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">mi_register_output</a>(<a class="code" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>* out, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00385"></a><span class="lineno">  385</span>&#160; </div>
+<div class="line"><a name="l00391"></a><span class="lineno"><a class="line" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">  391</a></span>&#160;<span class="keyword">typedef</span> void (<a class="code" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a>)(<span class="keywordtype">int</span> err, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00392"></a><span class="lineno">  392</span>&#160; </div>
+<div class="line"><a name="l00408"></a><span class="lineno"><a class="line" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">  408</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">mi_register_error</a>(<a class="code" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a>* errfun, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00409"></a><span class="lineno">  409</span>&#160; </div>
+<div class="line"><a name="l00414"></a><span class="lineno"><a class="line" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">  414</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a>(<span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00415"></a><span class="lineno">  415</span>&#160; </div>
+<div class="line"><a name="l00424"></a><span class="lineno"><a class="line" href="group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767">  424</a></span>&#160;<span class="keywordtype">int</span>  <a class="code" href="group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767">mi_reserve_os_memory</a>(<span class="keywordtype">size_t</span> size, <span class="keywordtype">bool</span> commit, <span class="keywordtype">bool</span> allow_large);</div>
+<div class="line"><a name="l00425"></a><span class="lineno">  425</span>&#160; </div>
+<div class="line"><a name="l00437"></a><span class="lineno"><a class="line" href="group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">  437</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">mi_manage_os_memory</a>(<span class="keywordtype">void</span>* start, <span class="keywordtype">size_t</span> size, <span class="keywordtype">bool</span> is_committed, <span class="keywordtype">bool</span> is_large, <span class="keywordtype">bool</span> is_zero, <span class="keywordtype">int</span> numa_node);</div>
+<div class="line"><a name="l00438"></a><span class="lineno">  438</span>&#160; </div>
+<div class="line"><a name="l00451"></a><span class="lineno"><a class="line" href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">  451</a></span>&#160;<span class="keywordtype">int</span> <a class="code" href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">mi_reserve_huge_os_pages_interleave</a>(<span class="keywordtype">size_t</span> pages, <span class="keywordtype">size_t</span> numa_nodes, <span class="keywordtype">size_t</span> timeout_msecs);</div>
+<div class="line"><a name="l00452"></a><span class="lineno">  452</span>&#160; </div>
+<div class="line"><a name="l00465"></a><span class="lineno"><a class="line" href="group__extended.html#ga7795a13d20087447281858d2c771cca1">  465</a></span>&#160;<span class="keywordtype">int</span> <a class="code" href="group__extended.html#ga7795a13d20087447281858d2c771cca1">mi_reserve_huge_os_pages_at</a>(<span class="keywordtype">size_t</span> pages, <span class="keywordtype">int</span> numa_node, <span class="keywordtype">size_t</span> timeout_msecs);</div>
+<div class="line"><a name="l00466"></a><span class="lineno">  466</span>&#160; </div>
+<div class="line"><a name="l00467"></a><span class="lineno">  467</span>&#160; </div>
+<div class="line"><a name="l00472"></a><span class="lineno"><a class="line" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">  472</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a>();</div>
+<div class="line"><a name="l00473"></a><span class="lineno">  473</span>&#160; </div>
+<div class="line"><a name="l00487"></a><span class="lineno"><a class="line" href="group__extended.html#ga7d862c2affd5790381da14eb102a364d">  487</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__extended.html#ga7d862c2affd5790381da14eb102a364d">mi_process_info</a>(<span class="keywordtype">size_t</span>* elapsed_msecs, <span class="keywordtype">size_t</span>* user_msecs, <span class="keywordtype">size_t</span>* system_msecs, <span class="keywordtype">size_t</span>* current_rss, <span class="keywordtype">size_t</span>* peak_rss, <span class="keywordtype">size_t</span>* current_commit, <span class="keywordtype">size_t</span>* peak_commit, <span class="keywordtype">size_t</span>* page_faults);</div>
+<div class="line"><a name="l00488"></a><span class="lineno">  488</span>&#160; </div>
+<div class="line"><a name="l00490"></a><span class="lineno">  490</span>&#160; </div>
+<div class="line"><a name="l00491"></a><span class="lineno">  491</span>&#160;<span class="comment">// ------------------------------------------------------</span></div>
+<div class="line"><a name="l00492"></a><span class="lineno">  492</span>&#160;<span class="comment">// Aligned allocation</span></div>
+<div class="line"><a name="l00493"></a><span class="lineno">  493</span>&#160;<span class="comment">// ------------------------------------------------------</span></div>
+<div class="line"><a name="l00494"></a><span class="lineno">  494</span>&#160; </div>
+<div class="line"><a name="l00500"></a><span class="lineno">  500</span>&#160; </div>
+<div class="line"><a name="l00502"></a><span class="lineno"><a class="line" href="group__aligned.html#ga83c03016066b438f51a8095e9140be06">  502</a></span>&#160;<span class="preprocessor">#define MI_ALIGNMENT_MAX   (1024*1024UL)   </span></div>
+<div class="line"><a name="l00503"></a><span class="lineno">  503</span>&#160; </div>
+<div class="line"><a name="l00516"></a><span class="lineno"><a class="line" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56">  516</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56">mi_malloc_aligned</a>(<span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00517"></a><span class="lineno"><a class="line" href="group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819">  517</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819">mi_zalloc_aligned</a>(<span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00518"></a><span class="lineno"><a class="line" href="group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9">  518</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9">mi_calloc_aligned</a>(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00519"></a><span class="lineno"><a class="line" href="group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae">  519</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae">mi_realloc_aligned</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00520"></a><span class="lineno">  520</span>&#160; </div>
+<div class="line"><a name="l00531"></a><span class="lineno"><a class="line" href="group__aligned.html#ga5850da130c936bd77db039dcfbc8295d">  531</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga5850da130c936bd77db039dcfbc8295d">mi_malloc_aligned_at</a>(<span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00532"></a><span class="lineno"><a class="line" href="group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8">  532</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8">mi_zalloc_aligned_at</a>(<span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00533"></a><span class="lineno"><a class="line" href="group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3">  533</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3">mi_calloc_aligned_at</a>(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00534"></a><span class="lineno"><a class="line" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">  534</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb">mi_realloc_aligned_at</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00535"></a><span class="lineno">  535</span>&#160; </div>
+<div class="line"><a name="l00537"></a><span class="lineno">  537</span>&#160; </div>
+<div class="line"><a name="l00543"></a><span class="lineno">  543</span>&#160; </div>
+<div class="line"><a name="l00548"></a><span class="lineno">  548</span>&#160;<span class="keyword">struct </span>mi_heap_s;</div>
+<div class="line"><a name="l00549"></a><span class="lineno">  549</span>&#160; </div>
+<div class="line"><a name="l00554"></a><span class="lineno">  554</span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>mi_heap_s <a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>;</div>
+<div class="line"><a name="l00555"></a><span class="lineno">  555</span>&#160; </div>
+<div class="line"><a name="l00557"></a><span class="lineno"><a class="line" href="group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">  557</a></span>&#160;<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* <a class="code" href="group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">mi_heap_new</a>();</div>
+<div class="line"><a name="l00558"></a><span class="lineno">  558</span>&#160; </div>
+<div class="line"><a name="l00566"></a><span class="lineno"><a class="line" href="group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409">  566</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409">mi_heap_delete</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap);</div>
+<div class="line"><a name="l00567"></a><span class="lineno">  567</span>&#160; </div>
+<div class="line"><a name="l00575"></a><span class="lineno"><a class="line" href="group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d">  575</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d">mi_heap_destroy</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap);</div>
+<div class="line"><a name="l00576"></a><span class="lineno">  576</span>&#160; </div>
+<div class="line"><a name="l00580"></a><span class="lineno"><a class="line" href="group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422">  580</a></span>&#160;<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* <a class="code" href="group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422">mi_heap_set_default</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap);</div>
+<div class="line"><a name="l00581"></a><span class="lineno">  581</span>&#160; </div>
+<div class="line"><a name="l00584"></a><span class="lineno"><a class="line" href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05">  584</a></span>&#160;<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* <a class="code" href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05">mi_heap_get_default</a>();</div>
+<div class="line"><a name="l00585"></a><span class="lineno">  585</span>&#160; </div>
+<div class="line"><a name="l00591"></a><span class="lineno"><a class="line" href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">  591</a></span>&#160;<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* <a class="code" href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">mi_heap_get_backing</a>();</div>
+<div class="line"><a name="l00592"></a><span class="lineno">  592</span>&#160; </div>
+<div class="line"><a name="l00594"></a><span class="lineno"><a class="line" href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">  594</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">mi_heap_collect</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">bool</span> force);</div>
+<div class="line"><a name="l00595"></a><span class="lineno">  595</span>&#160; </div>
+<div class="line"><a name="l00598"></a><span class="lineno"><a class="line" href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">  598</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">mi_heap_malloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00599"></a><span class="lineno">  599</span>&#160; </div>
+<div class="line"><a name="l00603"></a><span class="lineno"><a class="line" href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">  603</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">mi_heap_malloc_small</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00604"></a><span class="lineno">  604</span>&#160; </div>
+<div class="line"><a name="l00607"></a><span class="lineno"><a class="line" href="group__heap.html#ga903104592c8ed53417a3762da6241133">  607</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga903104592c8ed53417a3762da6241133">mi_heap_zalloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00608"></a><span class="lineno">  608</span>&#160; </div>
+<div class="line"><a name="l00611"></a><span class="lineno"><a class="line" href="group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55">  611</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55">mi_heap_calloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00612"></a><span class="lineno">  612</span>&#160; </div>
+<div class="line"><a name="l00615"></a><span class="lineno"><a class="line" href="group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0">  615</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0">mi_heap_mallocn</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00616"></a><span class="lineno">  616</span>&#160; </div>
+<div class="line"><a name="l00619"></a><span class="lineno"><a class="line" href="group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">  619</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">mi_heap_strdup</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <span class="keywordtype">char</span>* s);</div>
+<div class="line"><a name="l00620"></a><span class="lineno">  620</span>&#160; </div>
+<div class="line"><a name="l00623"></a><span class="lineno"><a class="line" href="group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a">  623</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a">mi_heap_strndup</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <span class="keywordtype">char</span>* s, <span class="keywordtype">size_t</span> n);</div>
+<div class="line"><a name="l00624"></a><span class="lineno">  624</span>&#160; </div>
+<div class="line"><a name="l00627"></a><span class="lineno"><a class="line" href="group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0">  627</a></span>&#160;<span class="keywordtype">char</span>* <a class="code" href="group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0">mi_heap_realpath</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">char</span>* resolved_name);</div>
+<div class="line"><a name="l00628"></a><span class="lineno">  628</span>&#160; </div>
+<div class="line"><a name="l00629"></a><span class="lineno"><a class="line" href="group__heap.html#gaaef3395f66be48f37bdc8322509c5d81">  629</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gaaef3395f66be48f37bdc8322509c5d81">mi_heap_realloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00630"></a><span class="lineno"><a class="line" href="group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8">  630</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8">mi_heap_reallocn</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00631"></a><span class="lineno"><a class="line" href="group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527">  631</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527">mi_heap_reallocf</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00632"></a><span class="lineno">  632</span>&#160; </div>
+<div class="line"><a name="l00633"></a><span class="lineno"><a class="line" href="group__heap.html#gab5b87e1805306f70df38789fcfcf6653">  633</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gab5b87e1805306f70df38789fcfcf6653">mi_heap_malloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00634"></a><span class="lineno"><a class="line" href="group__heap.html#ga23acd7680fb0976dde3783254c6c874b">  634</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga23acd7680fb0976dde3783254c6c874b">mi_heap_malloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00635"></a><span class="lineno"><a class="line" href="group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0">  635</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0">mi_heap_zalloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00636"></a><span class="lineno"><a class="line" href="group__heap.html#ga45fb43a62776fbebbdf1edd99b527954">  636</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga45fb43a62776fbebbdf1edd99b527954">mi_heap_zalloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00637"></a><span class="lineno"><a class="line" href="group__heap.html#ga4af03a6e2b93fae77424d93f889705c3">  637</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga4af03a6e2b93fae77424d93f889705c3">mi_heap_calloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00638"></a><span class="lineno"><a class="line" href="group__heap.html#ga08ca6419a5c057a4d965868998eef487">  638</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#ga08ca6419a5c057a4d965868998eef487">mi_heap_calloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00639"></a><span class="lineno"><a class="line" href="group__heap.html#gafc603b696bd14cae6da28658f950d98c">  639</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gafc603b696bd14cae6da28658f950d98c">mi_heap_realloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00640"></a><span class="lineno"><a class="line" href="group__heap.html#gaf96c788a1bf553fe2d371de9365e047c">  640</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__heap.html#gaf96c788a1bf553fe2d371de9365e047c">mi_heap_realloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00641"></a><span class="lineno">  641</span>&#160; </div>
+<div class="line"><a name="l00643"></a><span class="lineno">  643</span>&#160; </div>
+<div class="line"><a name="l00644"></a><span class="lineno">  644</span>&#160; </div>
+<div class="line"><a name="l00653"></a><span class="lineno">  653</span>&#160; </div>
+<div class="line"><a name="l00654"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6">  654</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6">mi_rezalloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00655"></a><span class="lineno">  655</span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">mi_recalloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size) ;</div>
+<div class="line"><a name="l00656"></a><span class="lineno">  656</span>&#160; </div>
+<div class="line"><a name="l00657"></a><span class="lineno"><a class="line" href="group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0">  657</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0">mi_rezalloc_aligned</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00658"></a><span class="lineno"><a class="line" href="group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1">  658</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1">mi_rezalloc_aligned_at</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00659"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f">  659</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f">mi_recalloc_aligned</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00660"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9">  660</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9">mi_recalloc_aligned_at</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00661"></a><span class="lineno">  661</span>&#160; </div>
+<div class="line"><a name="l00662"></a><span class="lineno"><a class="line" href="group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76">  662</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76">mi_heap_rezalloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00663"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd">  663</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd">mi_heap_recalloc</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00664"></a><span class="lineno">  664</span>&#160; </div>
+<div class="line"><a name="l00665"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664">  665</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664">mi_heap_rezalloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00666"></a><span class="lineno"><a class="line" href="group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb">  666</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb">mi_heap_rezalloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00667"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3">  667</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3">mi_heap_recalloc_aligned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00668"></a><span class="lineno"><a class="line" href="group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7">  668</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7">mi_heap_recalloc_aligned_at</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> offset);</div>
+<div class="line"><a name="l00669"></a><span class="lineno">  669</span>&#160; </div>
+<div class="line"><a name="l00671"></a><span class="lineno">  671</span>&#160; </div>
+<div class="line"><a name="l00680"></a><span class="lineno">  680</span>&#160; </div>
+<div class="line"><a name="l00692"></a><span class="lineno"><a class="line" href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">  692</a></span>&#160;<span class="preprocessor">#define mi_malloc_tp(tp)        ((tp*)mi_malloc(sizeof(tp)))</span></div>
+<div class="line"><a name="l00693"></a><span class="lineno">  693</span>&#160; </div>
+<div class="line"><a name="l00695"></a><span class="lineno"><a class="line" href="group__typed.html#gac77a61bdaf680a803785fe307820b48c">  695</a></span>&#160;<span class="preprocessor">#define mi_zalloc_tp(tp)        ((tp*)mi_zalloc(sizeof(tp)))</span></div>
+<div class="line"><a name="l00696"></a><span class="lineno">  696</span>&#160; </div>
+<div class="line"><a name="l00698"></a><span class="lineno"><a class="line" href="group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07">  698</a></span>&#160;<span class="preprocessor">#define mi_calloc_tp(tp,count)      ((tp*)mi_calloc(count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00699"></a><span class="lineno">  699</span>&#160; </div>
+<div class="line"><a name="l00701"></a><span class="lineno"><a class="line" href="group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b">  701</a></span>&#160;<span class="preprocessor">#define mi_mallocn_tp(tp,count)     ((tp*)mi_mallocn(count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00702"></a><span class="lineno">  702</span>&#160; </div>
+<div class="line"><a name="l00704"></a><span class="lineno"><a class="line" href="group__typed.html#ga1158b49a55dfa81f58a4426a7578f523">  704</a></span>&#160;<span class="preprocessor">#define mi_reallocn_tp(p,tp,count)  ((tp*)mi_reallocn(p,count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00705"></a><span class="lineno">  705</span>&#160; </div>
+<div class="line"><a name="l00707"></a><span class="lineno"><a class="line" href="group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7">  707</a></span>&#160;<span class="preprocessor">#define mi_heap_malloc_tp(hp,tp)        ((tp*)mi_heap_malloc(hp,sizeof(tp)))</span></div>
+<div class="line"><a name="l00708"></a><span class="lineno">  708</span>&#160; </div>
+<div class="line"><a name="l00710"></a><span class="lineno"><a class="line" href="group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe">  710</a></span>&#160;<span class="preprocessor">#define mi_heap_zalloc_tp(hp,tp)        ((tp*)mi_heap_zalloc(hp,sizeof(tp)))</span></div>
+<div class="line"><a name="l00711"></a><span class="lineno">  711</span>&#160; </div>
+<div class="line"><a name="l00713"></a><span class="lineno"><a class="line" href="group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74">  713</a></span>&#160;<span class="preprocessor">#define mi_heap_calloc_tp(hp,tp,count)      ((tp*)mi_heap_calloc(hp,count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00714"></a><span class="lineno">  714</span>&#160; </div>
+<div class="line"><a name="l00716"></a><span class="lineno"><a class="line" href="group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83">  716</a></span>&#160;<span class="preprocessor">#define mi_heap_mallocn_tp(hp,tp,count)     ((tp*)mi_heap_mallocn(hp,count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00717"></a><span class="lineno">  717</span>&#160; </div>
+<div class="line"><a name="l00719"></a><span class="lineno"><a class="line" href="group__typed.html#gaf213d5422ec35e7f6caad827c79bc948">  719</a></span>&#160;<span class="preprocessor">#define mi_heap_reallocn_tp(hp,p,tp,count)  ((tp*)mi_heap_reallocn(p,count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00720"></a><span class="lineno">  720</span>&#160; </div>
+<div class="line"><a name="l00722"></a><span class="lineno"><a class="line" href="group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e">  722</a></span>&#160;<span class="preprocessor">#define mi_heap_recalloc_tp(hp,p,tp,count)  ((tp*)mi_heap_recalloc(p,count,sizeof(tp)))</span></div>
+<div class="line"><a name="l00723"></a><span class="lineno">  723</span>&#160; </div>
+<div class="line"><a name="l00725"></a><span class="lineno">  725</span>&#160; </div>
+<div class="line"><a name="l00731"></a><span class="lineno">  731</span>&#160; </div>
+<div class="line"><a name="l00738"></a><span class="lineno"><a class="line" href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af">  738</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af">mi_heap_contains_block</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00739"></a><span class="lineno">  739</span>&#160; </div>
+<div class="line"><a name="l00748"></a><span class="lineno"><a class="line" href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377">  748</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377">mi_heap_check_owned</a>(<a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00749"></a><span class="lineno">  749</span>&#160; </div>
+<div class="line"><a name="l00757"></a><span class="lineno"><a class="line" href="group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5">  757</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5">mi_check_owned</a>(<span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00758"></a><span class="lineno">  758</span>&#160; </div>
+<div class="line"><a name="l00761"></a><span class="lineno"><a class="line" href="group__analysis.html">  761</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span>mi_heap_area_s {</div>
+<div class="line"><a name="l00762"></a><span class="lineno"><a class="line" href="group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8">  762</a></span>&#160;  <span class="keywordtype">void</span>*  <a class="code" href="group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8">blocks</a>;      </div>
+<div class="line"><a name="l00763"></a><span class="lineno"><a class="line" href="group__analysis.html#ae848a3e6840414891035423948ca0383">  763</a></span>&#160;  <span class="keywordtype">size_t</span> <a class="code" href="group__analysis.html#ae848a3e6840414891035423948ca0383">reserved</a>;    </div>
+<div class="line"><a name="l00764"></a><span class="lineno"><a class="line" href="group__analysis.html#ab47526df656d8837ec3e97f11b83f835">  764</a></span>&#160;  <span class="keywordtype">size_t</span> <a class="code" href="group__analysis.html#ab47526df656d8837ec3e97f11b83f835">committed</a>;   </div>
+<div class="line"><a name="l00765"></a><span class="lineno"><a class="line" href="group__analysis.html#ab820302c5cd0df133eb8e51650a008b4">  765</a></span>&#160;  <span class="keywordtype">size_t</span> <a class="code" href="group__analysis.html#ab820302c5cd0df133eb8e51650a008b4">used</a>;        </div>
+<div class="line"><a name="l00766"></a><span class="lineno"><a class="line" href="group__analysis.html#a332a6c14d736a99699d5453a1cb04b41">  766</a></span>&#160;  <span class="keywordtype">size_t</span> <a class="code" href="group__analysis.html#a332a6c14d736a99699d5453a1cb04b41">block_size</a>;  </div>
+<div class="line"><a name="l00767"></a><span class="lineno">  767</span>&#160;} <a class="code" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a>;</div>
+<div class="line"><a name="l00768"></a><span class="lineno">  768</span>&#160; </div>
+<div class="line"><a name="l00776"></a><span class="lineno"><a class="line" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">  776</a></span>&#160;<span class="keyword">typedef</span> bool (<a class="code" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a>)(<span class="keyword">const</span> <a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keyword">const</span> <a class="code" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a>* area, <span class="keywordtype">void</span>* block, <span class="keywordtype">size_t</span> block_size, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00777"></a><span class="lineno">  777</span>&#160; </div>
+<div class="line"><a name="l00789"></a><span class="lineno"><a class="line" href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed">  789</a></span>&#160;<span class="keywordtype">bool</span> <a class="code" href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed">mi_heap_visit_blocks</a>(<span class="keyword">const</span> <a class="code" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a>* heap, <span class="keywordtype">bool</span> visit_all_blocks, <a class="code" href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a>* visitor, <span class="keywordtype">void</span>* arg);</div>
+<div class="line"><a name="l00790"></a><span class="lineno">  790</span>&#160; </div>
+<div class="line"><a name="l00792"></a><span class="lineno">  792</span>&#160; </div>
+<div class="line"><a name="l00798"></a><span class="lineno">  798</span>&#160; </div>
+<div class="line"><a name="l00800"></a><span class="lineno"><a class="line" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">  800</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> mi_option_e {</div>
+<div class="line"><a name="l00801"></a><span class="lineno">  801</span>&#160;  <span class="comment">// stable options</span></div>
+<div class="line"><a name="l00802"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">  802</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">mi_option_show_errors</a>,  </div>
+<div class="line"><a name="l00803"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">  803</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">mi_option_show_stats</a>,   </div>
+<div class="line"><a name="l00804"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">  804</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">mi_option_verbose</a>,      </div>
+<div class="line"><a name="l00805"></a><span class="lineno">  805</span>&#160;  <span class="comment">// the following options are experimental</span></div>
+<div class="line"><a name="l00806"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">  806</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">mi_option_eager_commit</a>, </div>
+<div class="line"><a name="l00807"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">  807</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">mi_option_eager_region_commit</a>, </div>
+<div class="line"><a name="l00808"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">  808</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">mi_option_large_os_pages</a>,      </div>
+<div class="line"><a name="l00809"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2">  809</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2">mi_option_reserve_huge_os_pages</a>, </div>
+<div class="line"><a name="l00810"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c">  810</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c">mi_option_reserve_huge_os_pages_at</a>, </div>
+<div class="line"><a name="l00811"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">  811</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a>,   </div>
+<div class="line"><a name="l00812"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">  812</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>,      </div>
+<div class="line"><a name="l00813"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">  813</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a>,   </div>
+<div class="line"><a name="l00814"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5">  814</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5">mi_option_reset_delay</a>,     </div>
+<div class="line"><a name="l00815"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74">  815</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74">mi_option_use_numa_nodes</a>,  </div>
+<div class="line"><a name="l00816"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">  816</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>, </div>
+<div class="line"><a name="l00817"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">  817</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a>,  </div>
+<div class="line"><a name="l00818"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">  818</a></span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a>,          </div>
+<div class="line"><a name="l00819"></a><span class="lineno">  819</span>&#160;  <a class="code" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a></div>
+<div class="line"><a name="l00820"></a><span class="lineno"><a class="line" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">  820</a></span>&#160;} <a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a>;</div>
+<div class="line"><a name="l00821"></a><span class="lineno">  821</span>&#160; </div>
+<div class="line"><a name="l00822"></a><span class="lineno">  822</span>&#160; </div>
+<div class="line"><a name="l00823"></a><span class="lineno"><a class="line" href="group__options.html#ga459ad98f18b3fc9275474807fe0ca188">  823</a></span>&#160;<span class="keywordtype">bool</span>  <a class="code" href="group__options.html#ga459ad98f18b3fc9275474807fe0ca188">mi_option_is_enabled</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option);</div>
+<div class="line"><a name="l00824"></a><span class="lineno"><a class="line" href="group__options.html#ga04180ae41b0d601421dd62ced40ca050">  824</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#ga04180ae41b0d601421dd62ced40ca050">mi_option_enable</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option);</div>
+<div class="line"><a name="l00825"></a><span class="lineno"><a class="line" href="group__options.html#gaebf6ff707a2e688ebb1a2296ca564054">  825</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#gaebf6ff707a2e688ebb1a2296ca564054">mi_option_disable</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option);</div>
+<div class="line"><a name="l00826"></a><span class="lineno"><a class="line" href="group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed">  826</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed">mi_option_set_enabled</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, <span class="keywordtype">bool</span> enable);</div>
+<div class="line"><a name="l00827"></a><span class="lineno"><a class="line" href="group__options.html#ga65518b69ec5d32336b50e07f74b3f629">  827</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#ga65518b69ec5d32336b50e07f74b3f629">mi_option_set_enabled_default</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, <span class="keywordtype">bool</span> enable);</div>
+<div class="line"><a name="l00828"></a><span class="lineno">  828</span>&#160; </div>
+<div class="line"><a name="l00829"></a><span class="lineno"><a class="line" href="group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a">  829</a></span>&#160;<span class="keywordtype">long</span>  <a class="code" href="group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a">mi_option_get</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option);</div>
+<div class="line"><a name="l00830"></a><span class="lineno"><a class="line" href="group__options.html#gaf84921c32375e25754dc2ee6a911fa60">  830</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#gaf84921c32375e25754dc2ee6a911fa60">mi_option_set</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, <span class="keywordtype">long</span> value);</div>
+<div class="line"><a name="l00831"></a><span class="lineno"><a class="line" href="group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90">  831</a></span>&#160;<span class="keywordtype">void</span>  <a class="code" href="group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90">mi_option_set_default</a>(<a class="code" href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a> option, <span class="keywordtype">long</span> value);</div>
+<div class="line"><a name="l00832"></a><span class="lineno">  832</span>&#160; </div>
+<div class="line"><a name="l00833"></a><span class="lineno">  833</span>&#160; </div>
+<div class="line"><a name="l00835"></a><span class="lineno">  835</span>&#160; </div>
+<div class="line"><a name="l00842"></a><span class="lineno">  842</span>&#160; </div>
+<div class="line"><a name="l00843"></a><span class="lineno">  843</span>&#160;<span class="keywordtype">void</span>*  <a class="code" href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">mi_recalloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00844"></a><span class="lineno"><a class="line" href="group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de">  844</a></span>&#160;<span class="keywordtype">size_t</span> <a class="code" href="group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de">mi_malloc_size</a>(<span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00845"></a><span class="lineno"><a class="line" href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">  845</a></span>&#160;<span class="keywordtype">size_t</span> <a class="code" href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">mi_malloc_usable_size</a>(<span class="keyword">const</span> <span class="keywordtype">void</span> *p);</div>
+<div class="line"><a name="l00846"></a><span class="lineno">  846</span>&#160; </div>
+<div class="line"><a name="l00848"></a><span class="lineno"><a class="line" href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">  848</a></span>&#160;<span class="keywordtype">void</span>   <a class="code" href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">mi_cfree</a>(<span class="keywordtype">void</span>* p);</div>
+<div class="line"><a name="l00849"></a><span class="lineno">  849</span>&#160; </div>
+<div class="line"><a name="l00850"></a><span class="lineno"><a class="line" href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">  850</a></span>&#160;<span class="keywordtype">int</span> <a class="code" href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">mi_posix_memalign</a>(<span class="keywordtype">void</span>** p, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00851"></a><span class="lineno"><a class="line" href="group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a">  851</a></span>&#160;<span class="keywordtype">int</span> <a class="code" href="group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a">mi__posix_memalign</a>(<span class="keywordtype">void</span>** p, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00852"></a><span class="lineno"><a class="line" href="group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e">  852</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e">mi_memalign</a>(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00853"></a><span class="lineno"><a class="line" href="group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b">  853</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b">mi_valloc</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00854"></a><span class="lineno">  854</span>&#160; </div>
+<div class="line"><a name="l00855"></a><span class="lineno"><a class="line" href="group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e">  855</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e">mi_pvalloc</a>(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00856"></a><span class="lineno"><a class="line" href="group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5">  856</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5">mi_aligned_alloc</a>(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00857"></a><span class="lineno">  857</span>&#160; </div>
+<div class="line"><a name="l00860"></a><span class="lineno"><a class="line" href="group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088">  860</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088">mi_reallocarray</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00861"></a><span class="lineno">  861</span>&#160; </div>
+<div class="line"><a name="l00863"></a><span class="lineno"><a class="line" href="group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5">  863</a></span>&#160;<span class="keywordtype">int</span>   <a class="code" href="group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5">mi_reallocarr</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00864"></a><span class="lineno">  864</span>&#160; </div>
+<div class="line"><a name="l00865"></a><span class="lineno"><a class="line" href="group__posix.html#gae01389eedab8d67341ff52e2aad80ebb">  865</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__posix.html#gae01389eedab8d67341ff52e2aad80ebb">mi_free_size</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00866"></a><span class="lineno"><a class="line" href="group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc">  866</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc">mi_free_size_aligned</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00867"></a><span class="lineno"><a class="line" href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">  867</a></span>&#160;<span class="keywordtype">void</span> <a class="code" href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">mi_free_aligned</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00868"></a><span class="lineno">  868</span>&#160; </div>
+<div class="line"><a name="l00870"></a><span class="lineno">  870</span>&#160; </div>
+<div class="line"><a name="l00883"></a><span class="lineno">  883</span>&#160; </div>
+<div class="line"><a name="l00885"></a><span class="lineno"><a class="line" href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">  885</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">mi_new</a>(std::size_t n) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l00886"></a><span class="lineno">  886</span>&#160; </div>
+<div class="line"><a name="l00888"></a><span class="lineno"><a class="line" href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">  888</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">mi_new_n</a>(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l00889"></a><span class="lineno">  889</span>&#160; </div>
+<div class="line"><a name="l00891"></a><span class="lineno"><a class="line" href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">  891</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a>(std::size_t n, std::align_val_t alignment) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l00892"></a><span class="lineno">  892</span>&#160; </div>
+<div class="line"><a name="l00894"></a><span class="lineno"><a class="line" href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">  894</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">mi_new_nothrow</a>(<span class="keywordtype">size_t</span> n);</div>
+<div class="line"><a name="l00895"></a><span class="lineno">  895</span>&#160; </div>
+<div class="line"><a name="l00897"></a><span class="lineno"><a class="line" href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">  897</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a>(<span class="keywordtype">size_t</span> n, <span class="keywordtype">size_t</span> alignment);</div>
+<div class="line"><a name="l00898"></a><span class="lineno">  898</span>&#160; </div>
+<div class="line"><a name="l00900"></a><span class="lineno"><a class="line" href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">  900</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">mi_new_realloc</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><a name="l00901"></a><span class="lineno">  901</span>&#160; </div>
+<div class="line"><a name="l00903"></a><span class="lineno"><a class="line" href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">  903</a></span>&#160;<span class="keywordtype">void</span>* <a class="code" href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">mi_new_reallocn</a>(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newcount, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><a name="l00904"></a><span class="lineno">  904</span>&#160; </div>
+<div class="line"><a name="l00912"></a><span class="lineno"><a class="line" href="group__cpp.html">  912</a></span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">class</span> T&gt; <span class="keyword">struct </span><a class="code" href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator</a> { }</div>
+<div class="line"><a name="l00913"></a><span class="lineno">  913</span>&#160; </div>
+<div class="line"><a name="l00915"></a><span class="lineno">  915</span>&#160; </div>
+<div class="ttc" id="agroup__aligned_html_ga08647c4593f3b2eef24a919a73eba3a3"><div class="ttname"><a href="group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3">mi_calloc_aligned_at</a></div><div class="ttdeci">void * mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__aligned_html_ga0cadbcf5b89a7b6fb171bc8df8734819"><div class="ttname"><a href="group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819">mi_zalloc_aligned</a></div><div class="ttdeci">void * mi_zalloc_aligned(size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__aligned_html_ga4028d1cf4aa4c87c880747044a8322ae"><div class="ttname"><a href="group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae">mi_realloc_aligned</a></div><div class="ttdeci">void * mi_realloc_aligned(void *p, size_t newsize, size_t alignment)</div></div>
+<div class="ttc" id="agroup__aligned_html_ga53dddb4724042a90315b94bc268fb4c9"><div class="ttname"><a href="group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9">mi_calloc_aligned</a></div><div class="ttdeci">void * mi_calloc_aligned(size_t count, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__aligned_html_ga5850da130c936bd77db039dcfbc8295d"><div class="ttname"><a href="group__aligned.html#ga5850da130c936bd77db039dcfbc8295d">mi_malloc_aligned_at</a></div><div class="ttdeci">void * mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset)</div><div class="ttdoc">Allocate size bytes aligned by alignment at a specified offset.</div></div>
+<div class="ttc" id="agroup__aligned_html_ga5f8c2353766db522565e642fafd8a3f8"><div class="ttname"><a href="group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8">mi_zalloc_aligned_at</a></div><div class="ttdeci">void * mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__aligned_html_ga68930196751fa2cca9e1fd0d71bade56"><div class="ttname"><a href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56">mi_malloc_aligned</a></div><div class="ttdeci">void * mi_malloc_aligned(size_t size, size_t alignment)</div><div class="ttdoc">Allocate size bytes aligned by alignment.</div></div>
+<div class="ttc" id="agroup__aligned_html_gaf66a9ae6c6f08bd6be6fb6ea771faffb"><div class="ttname"><a href="group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb">mi_realloc_aligned_at</a></div><div class="ttdeci">void * mi_realloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__analysis_html_a332a6c14d736a99699d5453a1cb04b41"><div class="ttname"><a href="group__analysis.html#a332a6c14d736a99699d5453a1cb04b41">mi_heap_area_t::block_size</a></div><div class="ttdeci">size_t block_size</div><div class="ttdoc">size in bytes of one block</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:766</div></div>
+<div class="ttc" id="agroup__analysis_html_ab47526df656d8837ec3e97f11b83f835"><div class="ttname"><a href="group__analysis.html#ab47526df656d8837ec3e97f11b83f835">mi_heap_area_t::committed</a></div><div class="ttdeci">size_t committed</div><div class="ttdoc">current committed bytes of this area</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:764</div></div>
+<div class="ttc" id="agroup__analysis_html_ab820302c5cd0df133eb8e51650a008b4"><div class="ttname"><a href="group__analysis.html#ab820302c5cd0df133eb8e51650a008b4">mi_heap_area_t::used</a></div><div class="ttdeci">size_t used</div><div class="ttdoc">bytes in use by allocated blocks</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:765</div></div>
+<div class="ttc" id="agroup__analysis_html_ae0085e6e1cf059a4eb7767e30e9991b8"><div class="ttname"><a href="group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8">mi_heap_area_t::blocks</a></div><div class="ttdeci">void * blocks</div><div class="ttdoc">start of the area containing heap blocks</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:762</div></div>
+<div class="ttc" id="agroup__analysis_html_ae848a3e6840414891035423948ca0383"><div class="ttname"><a href="group__analysis.html#ae848a3e6840414891035423948ca0383">mi_heap_area_t::reserved</a></div><div class="ttdeci">size_t reserved</div><div class="ttdoc">bytes reserved for this area</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:763</div></div>
+<div class="ttc" id="agroup__analysis_html_ga0d67c1789faaa15ff366c024fcaf6377"><div class="ttname"><a href="group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377">mi_heap_check_owned</a></div><div class="ttdeci">bool mi_heap_check_owned(mi_heap_t *heap, const void *p)</div><div class="ttdoc">Check safely if any pointer is part of a heap.</div></div>
+<div class="ttc" id="agroup__analysis_html_ga628c237489c2679af84a4d0d143b3dd5"><div class="ttname"><a href="group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5">mi_check_owned</a></div><div class="ttdeci">bool mi_check_owned(const void *p)</div><div class="ttdoc">Check safely if any pointer is part of the default heap of this thread.</div></div>
+<div class="ttc" id="agroup__analysis_html_ga70c46687dc6e9dc98b232b02646f8bed"><div class="ttname"><a href="group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed">mi_heap_visit_blocks</a></div><div class="ttdeci">bool mi_heap_visit_blocks(const mi_heap_t *heap, bool visit_all_blocks, mi_block_visit_fun *visitor, void *arg)</div><div class="ttdoc">Visit all areas and blocks in a heap.</div></div>
+<div class="ttc" id="agroup__analysis_html_gaa862aa8ed8d57d84cae41fc1022d71af"><div class="ttname"><a href="group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af">mi_heap_contains_block</a></div><div class="ttdeci">bool mi_heap_contains_block(mi_heap_t *heap, const void *p)</div><div class="ttdoc">Does a heap contain a pointer to a previously allocated block?</div></div>
+<div class="ttc" id="agroup__analysis_html_gadfa01e2900f0e5d515ad5506b26f6d65"><div class="ttname"><a href="group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65">mi_block_visit_fun</a></div><div class="ttdeci">bool() mi_block_visit_fun(const mi_heap_t *heap, const mi_heap_area_t *area, void *block, size_t block_size, void *arg)</div><div class="ttdoc">Visitor function passed to mi_heap_visit_blocks()</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:776</div></div>
+<div class="ttc" id="agroup__analysis_html_structmi__heap__area__t"><div class="ttname"><a href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a></div><div class="ttdoc">An area of heap space contains blocks of a single size.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:761</div></div>
+<div class="ttc" id="agroup__cpp_html_ga756f4b2bc6a7ecd0a90baea8e90c7907"><div class="ttname"><a href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">mi_new_reallocn</a></div><div class="ttdeci">void * mi_new_reallocn(void *p, size_t newcount, size_t size)</div><div class="ttdoc">like mi_reallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc excepti...</div></div>
+<div class="ttc" id="agroup__cpp_html_gaab78a32f55149e9fbf432d5288e38e1e"><div class="ttname"><a href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">mi_new_realloc</a></div><div class="ttdeci">void * mi_new_realloc(void *p, size_t newsize)</div><div class="ttdoc">like mi_realloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...</div></div>
+<div class="ttc" id="agroup__cpp_html_gaad048a9fce3d02c5909cd05c6ec24545"><div class="ttname"><a href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">mi_new</a></div><div class="ttdeci">void * mi_new(std::size_t n) noexcept(false)</div><div class="ttdoc">like mi_malloc(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exception...</div></div>
+<div class="ttc" id="agroup__cpp_html_gab5e29558926d934c3f1cae8c815f942c"><div class="ttname"><a href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a></div><div class="ttdeci">void * mi_new_aligned_nothrow(size_t n, size_t alignment)</div><div class="ttdoc">like mi_malloc_aligned, but when out of memory, use std::get_new_handler but return NULL on failure.</div></div>
+<div class="ttc" id="agroup__cpp_html_gae7bc4f56cd57ed3359060ff4f38bda81"><div class="ttname"><a href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">mi_new_n</a></div><div class="ttdeci">void * mi_new_n(size_t count, size_t size) noexcept(false)</div><div class="ttdoc">like mi_mallocn(), but when out of memory, use std::get_new_handler and raise std::bad_alloc exceptio...</div></div>
+<div class="ttc" id="agroup__cpp_html_gaeaded64eda71ed6b1d569d3e723abc4a"><div class="ttname"><a href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">mi_new_nothrow</a></div><div class="ttdeci">void * mi_new_nothrow(size_t n)</div><div class="ttdoc">like mi_malloc, but when out of memory, use std::get_new_handler but return NULL on failure.</div></div>
+<div class="ttc" id="agroup__cpp_html_gaef2c2bdb4f70857902d3c8903ac095f3"><div class="ttname"><a href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a></div><div class="ttdeci">void * mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false)</div><div class="ttdoc">like mi_malloc_aligned(), but when out of memory, use std::get_new_handler and raise std::bad_alloc e...</div></div>
+<div class="ttc" id="agroup__cpp_html_structmi__stl__allocator"><div class="ttname"><a href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator</a></div><div class="ttdoc">std::allocator implementation for mimalloc for use in STL containers.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:912</div></div>
+<div class="ttc" id="agroup__extended_html_ga00ec3324b6b2591c7fe3677baa30a767"><div class="ttname"><a href="group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767">mi_reserve_os_memory</a></div><div class="ttdeci">int mi_reserve_os_memory(size_t size, bool commit, bool allow_large)</div><div class="ttdoc">Reserve OS memory for use by mimalloc.</div></div>
+<div class="ttc" id="agroup__extended_html_ga089c859d9eddc5f9b4bd946cd53cebee"><div class="ttname"><a href="group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee">mi_usable_size</a></div><div class="ttdeci">size_t mi_usable_size(void *p)</div><div class="ttdoc">Return the available bytes in a memory block.</div></div>
+<div class="ttc" id="agroup__extended_html_ga0ae4581e85453456a0d658b2b98bf7bf"><div class="ttname"><a href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a></div><div class="ttdeci">void mi_thread_done(void)</div><div class="ttdoc">Uninitialize mimalloc on a thread.</div></div>
+<div class="ttc" id="agroup__extended_html_ga220f29f40a44404b0061c15bc1c31152"><div class="ttname"><a href="group__extended.html#ga220f29f40a44404b0061c15bc1c31152">mi_zalloc_small</a></div><div class="ttdeci">void * mi_zalloc_small(size_t size)</div><div class="ttdoc">Allocate a zero initialized small object.</div></div>
+<div class="ttc" id="agroup__extended_html_ga251d369cda3f1c2a955c555486ed90e5"><div class="ttname"><a href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a></div><div class="ttdeci">void() mi_error_fun(int err, void *arg)</div><div class="ttdoc">Type of error callback functions.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:391</div></div>
+<div class="ttc" id="agroup__extended_html_ga299dae78d25ce112e384a98b7309c5be"><div class="ttname"><a href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a></div><div class="ttdeci">void() mi_deferred_free_fun(bool force, unsigned long long heartbeat, void *arg)</div><div class="ttdoc">Type of deferred free functions.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:352</div></div>
+<div class="ttc" id="agroup__extended_html_ga2d126e5c62d3badc35445e5d84166df2"><div class="ttname"><a href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">mi_stats_print</a></div><div class="ttdeci">void mi_stats_print(void *out)</div><div class="ttdoc">Deprecated.</div></div>
+<div class="ttc" id="agroup__extended_html_ga3132f521fb756fc0e8ec0b74fb58df50"><div class="ttname"><a href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">mi_reserve_huge_os_pages_interleave</a></div><div class="ttdeci">int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs)</div><div class="ttdoc">Reserve pages of huge OS pages (1GiB) evenly divided over numa_nodes nodes, but stops after at most t...</div></div>
+<div class="ttc" id="agroup__extended_html_ga3460a6ca91af97be4058f523d3cb8ece"><div class="ttname"><a href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">mi_register_deferred_free</a></div><div class="ttdeci">void mi_register_deferred_free(mi_deferred_free_fun *deferred_free, void *arg)</div><div class="ttdoc">Register a deferred free function.</div></div>
+<div class="ttc" id="agroup__extended_html_ga3bb8468b8cfcc6e2a61d98aee85c5f99"><div class="ttname"><a href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a></div><div class="ttdeci">void mi_stats_reset(void)</div><div class="ttdoc">Reset statistics.</div></div>
+<div class="ttc" id="agroup__extended_html_ga421430e2226d7d468529cec457396756"><div class="ttname"><a href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a></div><div class="ttdeci">void mi_collect(bool force)</div><div class="ttdoc">Eagerly free memory.</div></div>
+<div class="ttc" id="agroup__extended_html_ga4c6486a1fdcd7a423b5f25fe4be8e0cf"><div class="ttname"><a href="group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf">mi_manage_os_memory</a></div><div class="ttdeci">bool mi_manage_os_memory(void *start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node)</div><div class="ttdoc">Manage a particular memory area for use by mimalloc.</div></div>
+<div class="ttc" id="agroup__extended_html_ga537f13b299ddf801e49a5a94fde02c79"><div class="ttname"><a href="group__extended.html#ga537f13b299ddf801e49a5a94fde02c79">mi_stats_print_out</a></div><div class="ttdeci">void mi_stats_print_out(mi_output_fun *out, void *arg)</div><div class="ttdoc">Print the main statistics.</div></div>
+<div class="ttc" id="agroup__extended_html_ga5f071b10d4df1c3658e04e7fd67a94e6"><div class="ttname"><a href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a></div><div class="ttdeci">bool mi_is_in_heap_region(const void *p)</div><div class="ttdoc">Is a pointer part of our heap?</div></div>
+<div class="ttc" id="agroup__extended_html_ga7136c2e55cb22c98ecf95d08d6debb99"><div class="ttname"><a href="group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99">mi_malloc_small</a></div><div class="ttdeci">void * mi_malloc_small(size_t size)</div><div class="ttdoc">Allocate a small object.</div></div>
+<div class="ttc" id="agroup__extended_html_ga7795a13d20087447281858d2c771cca1"><div class="ttname"><a href="group__extended.html#ga7795a13d20087447281858d2c771cca1">mi_reserve_huge_os_pages_at</a></div><div class="ttdeci">int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs)</div><div class="ttdoc">Reserve pages of huge OS pages (1GiB) at a specific numa_node, but stops after at most timeout_msecs ...</div></div>
+<div class="ttc" id="agroup__extended_html_ga7d862c2affd5790381da14eb102a364d"><div class="ttname"><a href="group__extended.html#ga7d862c2affd5790381da14eb102a364d">mi_process_info</a></div><div class="ttdeci">void mi_process_info(size_t *elapsed_msecs, size_t *user_msecs, size_t *system_msecs, size_t *current_rss, size_t *peak_rss, size_t *current_commit, size_t *peak_commit, size_t *page_faults)</div><div class="ttdoc">Return process information (time and memory usage).</div></div>
+<div class="ttc" id="agroup__extended_html_ga854b1de8cb067c7316286c28b2fcd3d1"><div class="ttname"><a href="group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1">mi_stats_merge</a></div><div class="ttdeci">void mi_stats_merge(void)</div><div class="ttdoc">Merge thread local statistics with the main statistics and reset.</div></div>
+<div class="ttc" id="agroup__extended_html_gaa1d55e0e894be240827e5d87ec3a1f45"><div class="ttname"><a href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">mi_register_error</a></div><div class="ttdeci">void mi_register_error(mi_error_fun *errfun, void *arg)</div><div class="ttdoc">Register an error callback function.</div></div>
+<div class="ttc" id="agroup__extended_html_gaad25050b19f30cd79397b227e0157a3f"><div class="ttname"><a href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a></div><div class="ttdeci">bool mi_is_redirected()</div><div class="ttdoc">Is the C runtime malloc API redirected?</div></div>
+<div class="ttc" id="agroup__extended_html_gab1dac8476c46cb9eecab767eb40c1525"><div class="ttname"><a href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">mi_thread_stats_print_out</a></div><div class="ttdeci">void mi_thread_stats_print_out(mi_output_fun *out, void *arg)</div><div class="ttdoc">Print out heap statistics for this thread.</div></div>
+<div class="ttc" id="agroup__extended_html_gac057927cd06c854b45fe7847e921bd47"><div class="ttname"><a href="group__extended.html#gac057927cd06c854b45fe7847e921bd47">mi_good_size</a></div><div class="ttdeci">size_t mi_good_size(size_t size)</div><div class="ttdoc">Return the used allocation size.</div></div>
+<div class="ttc" id="agroup__extended_html_gad823d23444a4b77a40f66bf075a98a0c"><div class="ttname"><a href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a></div><div class="ttdeci">void() mi_output_fun(const char *msg, void *arg)</div><div class="ttdoc">Type of output functions.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:376</div></div>
+<div class="ttc" id="agroup__extended_html_gae5b17ff027cd2150b43a33040250cf3f"><div class="ttname"><a href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">mi_register_output</a></div><div class="ttdeci">void mi_register_output(mi_output_fun *out, void *arg)</div><div class="ttdoc">Register an output function.</div></div>
+<div class="ttc" id="agroup__extended_html_gaf8e73efc2cbca9ebfdfb166983a04c17"><div class="ttname"><a href="group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17">mi_thread_init</a></div><div class="ttdeci">void mi_thread_init(void)</div><div class="ttdoc">Initialize mimalloc on a thread.</div></div>
+<div class="ttc" id="agroup__heap_html_ga00e95ba1e01acac3cfd95bb7a357a6f0"><div class="ttname"><a href="group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0">mi_heap_realpath</a></div><div class="ttdeci">char * mi_heap_realpath(mi_heap_t *heap, const char *fname, char *resolved_name)</div><div class="ttdoc">Resolve a file path name using a specific heap to allocate the result.</div></div>
+<div class="ttc" id="agroup__heap_html_ga08ca6419a5c057a4d965868998eef487"><div class="ttname"><a href="group__heap.html#ga08ca6419a5c057a4d965868998eef487">mi_heap_calloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_calloc_aligned_at(mi_heap_t *heap, size_t count, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__heap_html_ga139d6b09dbf50c3c2523d0f4d1cfdeb5"><div class="ttname"><a href="group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5">mi_heap_strdup</a></div><div class="ttdeci">char * mi_heap_strdup(mi_heap_t *heap, const char *s)</div><div class="ttdoc">Duplicate a string in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga23acd7680fb0976dde3783254c6c874b"><div class="ttname"><a href="group__heap.html#ga23acd7680fb0976dde3783254c6c874b">mi_heap_malloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_malloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__heap_html_ga2ab1af8d438819b55319c7ef51d1e409"><div class="ttname"><a href="group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409">mi_heap_delete</a></div><div class="ttdeci">void mi_heap_delete(mi_heap_t *heap)</div><div class="ttdoc">Delete a previously allocated heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga34a47cde5a5b38c29f1aa3c5e76943c2"><div class="ttname"><a href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a></div><div class="ttdeci">struct mi_heap_s mi_heap_t</div><div class="ttdoc">Type of first-class heaps.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:554</div></div>
+<div class="ttc" id="agroup__heap_html_ga45fb43a62776fbebbdf1edd99b527954"><div class="ttname"><a href="group__heap.html#ga45fb43a62776fbebbdf1edd99b527954">mi_heap_zalloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_zalloc_aligned_at(mi_heap_t *heap, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__heap_html_ga4a21070eb4e7cce018133c8d5f4b0527"><div class="ttname"><a href="group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527">mi_heap_reallocf</a></div><div class="ttdeci">void * mi_heap_reallocf(mi_heap_t *heap, void *p, size_t newsize)</div></div>
+<div class="ttc" id="agroup__heap_html_ga4af03a6e2b93fae77424d93f889705c3"><div class="ttname"><a href="group__heap.html#ga4af03a6e2b93fae77424d93f889705c3">mi_heap_calloc_aligned</a></div><div class="ttdeci">void * mi_heap_calloc_aligned(mi_heap_t *heap, size_t count, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__heap_html_ga5d03fbe062ffcf38f0f417fd968357fc"><div class="ttname"><a href="group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc">mi_heap_get_backing</a></div><div class="ttdeci">mi_heap_t * mi_heap_get_backing()</div><div class="ttdoc">Get the backing heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga766f672ba56f2fbfeb9d9dbb0b7f6b11"><div class="ttname"><a href="group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11">mi_heap_new</a></div><div class="ttdeci">mi_heap_t * mi_heap_new()</div><div class="ttdoc">Create a new heap that can be used for allocation.</div></div>
+<div class="ttc" id="agroup__heap_html_ga7922f7495cde30b1984d0e6072419298"><div class="ttname"><a href="group__heap.html#ga7922f7495cde30b1984d0e6072419298">mi_heap_collect</a></div><div class="ttdeci">void mi_heap_collect(mi_heap_t *heap, bool force)</div><div class="ttdoc">Release outstanding resources in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga851da6c43fe0b71c1376cee8aef90db0"><div class="ttname"><a href="group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0">mi_heap_mallocn</a></div><div class="ttdeci">void * mi_heap_mallocn(mi_heap_t *heap, size_t count, size_t size)</div><div class="ttdoc">Allocate count elements in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga8db4cbb87314a989a9a187464d6b5e05"><div class="ttname"><a href="group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05">mi_heap_get_default</a></div><div class="ttdeci">mi_heap_t * mi_heap_get_default()</div><div class="ttdoc">Get the default heap that is used for mi_malloc() et al.</div></div>
+<div class="ttc" id="agroup__heap_html_ga8e3dbd46650dd26573cf307a2c8f1f5a"><div class="ttname"><a href="group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a">mi_heap_strndup</a></div><div class="ttdeci">char * mi_heap_strndup(mi_heap_t *heap, const char *s, size_t n)</div><div class="ttdoc">Duplicate a string of at most length n in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga903104592c8ed53417a3762da6241133"><div class="ttname"><a href="group__heap.html#ga903104592c8ed53417a3762da6241133">mi_heap_zalloc</a></div><div class="ttdeci">void * mi_heap_zalloc(mi_heap_t *heap, size_t size)</div><div class="ttdoc">Allocate zero-initialized in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga9cbed01e42c0647907295de92c3fa296"><div class="ttname"><a href="group__heap.html#ga9cbed01e42c0647907295de92c3fa296">mi_heap_malloc</a></div><div class="ttdeci">void * mi_heap_malloc(mi_heap_t *heap, size_t size)</div><div class="ttdoc">Allocate in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_ga9f9c0844edb9717f4feacd79116b8e0d"><div class="ttname"><a href="group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d">mi_heap_destroy</a></div><div class="ttdeci">void mi_heap_destroy(mi_heap_t *heap)</div><div class="ttdoc">Destroy a heap, freeing all its still allocated blocks.</div></div>
+<div class="ttc" id="agroup__heap_html_gaa1a1c7a1f4da6826b5a25b70ef878368"><div class="ttname"><a href="group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368">mi_heap_malloc_small</a></div><div class="ttdeci">void * mi_heap_malloc_small(mi_heap_t *heap, size_t size)</div><div class="ttdoc">Allocate a small object in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_gaa450a59c6c7ae5fdbd1c2b80a8329ef0"><div class="ttname"><a href="group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0">mi_heap_zalloc_aligned</a></div><div class="ttdeci">void * mi_heap_zalloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__heap_html_gaa6702b3c48e9e53e50e81b36f5011d55"><div class="ttname"><a href="group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55">mi_heap_calloc</a></div><div class="ttdeci">void * mi_heap_calloc(mi_heap_t *heap, size_t count, size_t size)</div><div class="ttdoc">Allocate count zero-initialized elements in a specific heap.</div></div>
+<div class="ttc" id="agroup__heap_html_gaaef3395f66be48f37bdc8322509c5d81"><div class="ttname"><a href="group__heap.html#gaaef3395f66be48f37bdc8322509c5d81">mi_heap_realloc</a></div><div class="ttdeci">void * mi_heap_realloc(mi_heap_t *heap, void *p, size_t newsize)</div></div>
+<div class="ttc" id="agroup__heap_html_gab5b87e1805306f70df38789fcfcf6653"><div class="ttname"><a href="group__heap.html#gab5b87e1805306f70df38789fcfcf6653">mi_heap_malloc_aligned</a></div><div class="ttdeci">void * mi_heap_malloc_aligned(mi_heap_t *heap, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__heap_html_gab8631ec88c8d26641b68b5d25dcd4422"><div class="ttname"><a href="group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422">mi_heap_set_default</a></div><div class="ttdeci">mi_heap_t * mi_heap_set_default(mi_heap_t *heap)</div><div class="ttdoc">Set the default heap to use for mi_malloc() et al.</div></div>
+<div class="ttc" id="agroup__heap_html_gac74e94ad9b0c9b57c1c4d88b8825b7a8"><div class="ttname"><a href="group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8">mi_heap_reallocn</a></div><div class="ttdeci">void * mi_heap_reallocn(mi_heap_t *heap, void *p, size_t count, size_t size)</div></div>
+<div class="ttc" id="agroup__heap_html_gaf96c788a1bf553fe2d371de9365e047c"><div class="ttname"><a href="group__heap.html#gaf96c788a1bf553fe2d371de9365e047c">mi_heap_realloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_realloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__heap_html_gafc603b696bd14cae6da28658f950d98c"><div class="ttname"><a href="group__heap.html#gafc603b696bd14cae6da28658f950d98c">mi_heap_realloc_aligned</a></div><div class="ttdeci">void * mi_heap_realloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)</div></div>
+<div class="ttc" id="agroup__malloc_html_ga08cec32dd5bbe7da91c78d19f1b5bebe"><div class="ttname"><a href="group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe">mi_realpath</a></div><div class="ttdeci">char * mi_realpath(const char *fname, char *resolved_name)</div><div class="ttdoc">Resolve a file path name.</div></div>
+<div class="ttc" id="agroup__malloc_html_ga0b05e2bf0f73e7401ae08597ff782ac6"><div class="ttname"><a href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6">mi_mallocn</a></div><div class="ttdeci">void * mi_mallocn(size_t count, size_t size)</div><div class="ttdoc">Allocate count elements of size bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_ga23a0fbb452b5dce8e31fab1a1958cacc"><div class="ttname"><a href="group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc">mi_recalloc</a></div><div class="ttdeci">void * mi_recalloc(void *p, size_t count, size_t size)</div><div class="ttdoc">Re-allocate memory to count elements of size bytes, with extra memory initialized to zero.</div></div>
+<div class="ttc" id="agroup__malloc_html_ga3406e8b168bc74c8637b11571a6da83a"><div class="ttname"><a href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a">mi_malloc</a></div><div class="ttdeci">void * mi_malloc(size_t size)</div><div class="ttdoc">Allocate size bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_ga61d57b4144ba24fba5c1e9b956d13853"><div class="ttname"><a href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853">mi_reallocn</a></div><div class="ttdeci">void * mi_reallocn(void *p, size_t count, size_t size)</div><div class="ttdoc">Re-allocate memory to count elements of size bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_ga97fedb4f7107c592fd7f0f0a8949a57d"><div class="ttname"><a href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d">mi_calloc</a></div><div class="ttdeci">void * mi_calloc(size_t count, size_t size)</div><div class="ttdoc">Allocate zero-initialized count elements of size bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_gaaabf971c2571891433477e2d21a35266"><div class="ttname"><a href="group__malloc.html#gaaabf971c2571891433477e2d21a35266">mi_strndup</a></div><div class="ttdeci">char * mi_strndup(const char *s, size_t n)</div><div class="ttdoc">Allocate and duplicate a string up to n bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_gaaee66a1d483c3e28f585525fb96707e4"><div class="ttname"><a href="group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4">mi_expand</a></div><div class="ttdeci">void * mi_expand(void *p, size_t newsize)</div><div class="ttdoc">Try to re-allocate memory to newsize bytes in place.</div></div>
+<div class="ttc" id="agroup__malloc_html_gac7cffe13f1f458ed16789488bf92b9b2"><div class="ttname"><a href="group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2">mi_strdup</a></div><div class="ttdeci">char * mi_strdup(const char *s)</div><div class="ttdoc">Allocate and duplicate a string.</div></div>
+<div class="ttc" id="agroup__malloc_html_gaf11eb497da57bdfb2de65eb191c69db6"><div class="ttname"><a href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6">mi_realloc</a></div><div class="ttdeci">void * mi_realloc(void *p, size_t newsize)</div><div class="ttdoc">Re-allocate memory to newsize bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_gaf2c7b89c327d1f60f59e68b9ea644d95"><div class="ttname"><a href="group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95">mi_free</a></div><div class="ttdeci">void mi_free(void *p)</div><div class="ttdoc">Free previously allocated memory.</div></div>
+<div class="ttc" id="agroup__malloc_html_gafdd9d8bb2986e668ba9884f28af38000"><div class="ttname"><a href="group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000">mi_zalloc</a></div><div class="ttdeci">void * mi_zalloc(size_t size)</div><div class="ttdoc">Allocate zero-initialized size bytes.</div></div>
+<div class="ttc" id="agroup__malloc_html_gafe68ac7c5e24a65cd55c9d6b152211a0"><div class="ttname"><a href="group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0">mi_reallocf</a></div><div class="ttdeci">void * mi_reallocf(void *p, size_t newsize)</div><div class="ttdoc">Re-allocate memory to newsize bytes,.</div></div>
+<div class="ttc" id="agroup__options_html_ga04180ae41b0d601421dd62ced40ca050"><div class="ttname"><a href="group__options.html#ga04180ae41b0d601421dd62ced40ca050">mi_option_enable</a></div><div class="ttdeci">void mi_option_enable(mi_option_t option)</div></div>
+<div class="ttc" id="agroup__options_html_ga459ad98f18b3fc9275474807fe0ca188"><div class="ttname"><a href="group__options.html#ga459ad98f18b3fc9275474807fe0ca188">mi_option_is_enabled</a></div><div class="ttdeci">bool mi_option_is_enabled(mi_option_t option)</div></div>
+<div class="ttc" id="agroup__options_html_ga65518b69ec5d32336b50e07f74b3f629"><div class="ttname"><a href="group__options.html#ga65518b69ec5d32336b50e07f74b3f629">mi_option_set_enabled_default</a></div><div class="ttdeci">void mi_option_set_enabled_default(mi_option_t option, bool enable)</div></div>
+<div class="ttc" id="agroup__options_html_ga7e8af195cc81d3fa64ccf2662caa565a"><div class="ttname"><a href="group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a">mi_option_get</a></div><div class="ttdeci">long mi_option_get(mi_option_t option)</div></div>
+<div class="ttc" id="agroup__options_html_ga7ef623e440e6e5545cb08c94e71e4b90"><div class="ttname"><a href="group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90">mi_option_set_default</a></div><div class="ttdeci">void mi_option_set_default(mi_option_t option, long value)</div></div>
+<div class="ttc" id="agroup__options_html_ga9a13d05fcb77489cb06d4d017ebd8bed"><div class="ttname"><a href="group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed">mi_option_set_enabled</a></div><div class="ttdeci">void mi_option_set_enabled(mi_option_t option, bool enable)</div></div>
+<div class="ttc" id="agroup__options_html_gaebf6ff707a2e688ebb1a2296ca564054"><div class="ttname"><a href="group__options.html#gaebf6ff707a2e688ebb1a2296ca564054">mi_option_disable</a></div><div class="ttdeci">void mi_option_disable(mi_option_t option)</div></div>
+<div class="ttc" id="agroup__options_html_gaf84921c32375e25754dc2ee6a911fa60"><div class="ttname"><a href="group__options.html#gaf84921c32375e25754dc2ee6a911fa60">mi_option_set</a></div><div class="ttdeci">void mi_option_set(mi_option_t option, long value)</div></div>
+<div class="ttc" id="agroup__options_html_gafebf7ed116adb38ae5218bc3ce06884c"><div class="ttname"><a href="group__options.html#gafebf7ed116adb38ae5218bc3ce06884c">mi_option_t</a></div><div class="ttdeci">mi_option_t</div><div class="ttdoc">Runtime options.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:800</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda">mi_option_show_stats</a></div><div class="ttdeci">@ mi_option_show_stats</div><div class="ttdoc">Print statistics to stderr when the program is done.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:803</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74">mi_option_use_numa_nodes</a></div><div class="ttdeci">@ mi_option_use_numa_nodes</div><div class="ttdoc">Pretend there are at most N NUMA nodes.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:815</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5">mi_option_reset_delay</a></div><div class="ttdeci">@ mi_option_reset_delay</div><div class="ttdoc">Delay in milli-seconds before resetting a page (100ms by default)</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:814</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a></div><div class="ttdeci">@ mi_option_eager_commit_delay</div><div class="ttdoc">Experimental.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:817</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b">mi_option_eager_commit</a></div><div class="ttdeci">@ mi_option_eager_commit</div><div class="ttdoc">Eagerly commit segments (4MiB) (enabled by default).</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:806</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a></div><div class="ttdeci">@ mi_option_segment_cache</div><div class="ttdoc">The number of segments per thread to keep cached.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:811</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad">mi_option_eager_region_commit</a></div><div class="ttdeci">@ mi_option_eager_region_commit</div><div class="ttdoc">Eagerly commit large (256MiB) memory regions (enabled by default, except on Windows)</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:807</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e">mi_option_large_os_pages</a></div><div class="ttdeci">@ mi_option_large_os_pages</div><div class="ttdoc">Use large OS pages (2MiB in size) if possible.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:808</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a></div><div class="ttdeci">@ mi_option_os_tag</div><div class="ttdoc">OS tag to assign to mimalloc'd memory.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:818</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a></div><div class="ttdeci">@ _mi_option_last</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:819</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777">mi_option_verbose</a></div><div class="ttdeci">@ mi_option_verbose</div><div class="ttdoc">Print verbose messages to stderr.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:804</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c">mi_option_reserve_huge_os_pages_at</a></div><div class="ttdeci">@ mi_option_reserve_huge_os_pages_at</div><div class="ttdoc">Reserve huge OS pages at node N.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:810</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a></div><div class="ttdeci">@ mi_option_reset_decommits</div><div class="ttdoc">Experimental.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:816</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2">mi_option_reserve_huge_os_pages</a></div><div class="ttdeci">@ mi_option_reserve_huge_os_pages</div><div class="ttdoc">The number of huge OS pages (1GiB in size) to reserve at the start of the program.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:809</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a></div><div class="ttdeci">@ mi_option_page_reset</div><div class="ttdoc">Reset page memory after mi_option_reset_delay milliseconds when it becomes free.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:812</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a></div><div class="ttdeci">@ mi_option_segment_reset</div><div class="ttdoc">Experimental.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:813</div></div>
+<div class="ttc" id="agroup__options_html_ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0"><div class="ttname"><a href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0">mi_option_show_errors</a></div><div class="ttdeci">@ mi_option_show_errors</div><div class="ttdoc">Print error messages to stderr.</div><div class="ttdef"><b>Definition:</b> mimalloc-doc.h:802</div></div>
+<div class="ttc" id="agroup__posix_html_ga06d07cf357bbac5c73ba5d0c0c421e17"><div class="ttname"><a href="group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17">mi_malloc_usable_size</a></div><div class="ttdeci">size_t mi_malloc_usable_size(const void *p)</div></div>
+<div class="ttc" id="agroup__posix_html_ga0d28d5cf61e6bfbb18c63092939fe5c9"><div class="ttname"><a href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">mi_free_aligned</a></div><div class="ttdeci">void mi_free_aligned(void *p, size_t alignment)</div></div>
+<div class="ttc" id="agroup__posix_html_ga1326d2e4388630b5f81ca7206318b8e5"><div class="ttname"><a href="group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5">mi_aligned_alloc</a></div><div class="ttdeci">void * mi_aligned_alloc(size_t alignment, size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_ga4531c9e775bb3ae12db57c1ba8a5d7de"><div class="ttname"><a href="group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de">mi_malloc_size</a></div><div class="ttdeci">size_t mi_malloc_size(const void *p)</div></div>
+<div class="ttc" id="agroup__posix_html_ga48fad8648a2f1dab9c87ea9448a52088"><div class="ttname"><a href="group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088">mi_reallocarray</a></div><div class="ttdeci">void * mi_reallocarray(void *p, size_t count, size_t size)</div><div class="ttdoc">Correspond s to reallocarray in FreeBSD.</div></div>
+<div class="ttc" id="agroup__posix_html_ga705dc7a64bffacfeeb0141501a5c35d7"><div class="ttname"><a href="group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7">mi_cfree</a></div><div class="ttdeci">void mi_cfree(void *p)</div><div class="ttdoc">Just as free but also checks if the pointer p belongs to our heap.</div></div>
+<div class="ttc" id="agroup__posix_html_ga72e9d7ffb5fe94d69bc722c8506e27bc"><div class="ttname"><a href="group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc">mi_free_size_aligned</a></div><div class="ttdeci">void mi_free_size_aligned(void *p, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__posix_html_ga73baaf5951f5165ba0763d0c06b6a93b"><div class="ttname"><a href="group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b">mi_valloc</a></div><div class="ttdeci">void * mi_valloc(size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_ga7e1934d60a3e697950eeb48e042bfad5"><div class="ttname"><a href="group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5">mi_reallocarr</a></div><div class="ttdeci">int mi_reallocarr(void *p, size_t count, size_t size)</div><div class="ttdoc">Corresponds to reallocarr in NetBSD.</div></div>
+<div class="ttc" id="agroup__posix_html_gaab7fa71ea93b96873f5d9883db57d40e"><div class="ttname"><a href="group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e">mi_memalign</a></div><div class="ttdeci">void * mi_memalign(size_t alignment, size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_gacff84f226ba9feb2031b8992e5579447"><div class="ttname"><a href="group__posix.html#gacff84f226ba9feb2031b8992e5579447">mi_posix_memalign</a></div><div class="ttdeci">int mi_posix_memalign(void **p, size_t alignment, size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_gad5a69c8fea96aa2b7a7c818c2130090a"><div class="ttname"><a href="group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a">mi__posix_memalign</a></div><div class="ttdeci">int mi__posix_memalign(void **p, size_t alignment, size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_gae01389eedab8d67341ff52e2aad80ebb"><div class="ttname"><a href="group__posix.html#gae01389eedab8d67341ff52e2aad80ebb">mi_free_size</a></div><div class="ttdeci">void mi_free_size(void *p, size_t size)</div></div>
+<div class="ttc" id="agroup__posix_html_gaeb325c39b887d3b90d85d1eb1712fb1e"><div class="ttname"><a href="group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e">mi_pvalloc</a></div><div class="ttdeci">void * mi_pvalloc(size_t size)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga375fa8a611c51905e592d5d467c49664"><div class="ttname"><a href="group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664">mi_heap_rezalloc_aligned</a></div><div class="ttdeci">void * mi_heap_rezalloc_aligned(mi_heap_t *heap, void *p, size_t newsize, size_t alignment)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga3e7e5c291acf1c7fd7ffd9914a9f945f"><div class="ttname"><a href="group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f">mi_recalloc_aligned</a></div><div class="ttdeci">void * mi_recalloc_aligned(void *p, size_t newcount, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga496452c96f1de8c500be9fddf52edaf7"><div class="ttname"><a href="group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7">mi_heap_recalloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_recalloc_aligned_at(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga4ff5e92ad73585418a072c9d059e5cf9"><div class="ttname"><a href="group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9">mi_recalloc_aligned_at</a></div><div class="ttdeci">void * mi_recalloc_aligned_at(void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga8648c5fbb22a80f0262859099f06dfbd"><div class="ttname"><a href="group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd">mi_heap_recalloc</a></div><div class="ttdeci">void * mi_heap_recalloc(mi_heap_t *heap, void *p, size_t newcount, size_t size)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga8c292e142110229a2980b37ab036dbc6"><div class="ttname"><a href="group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6">mi_rezalloc</a></div><div class="ttdeci">void * mi_rezalloc(void *p, size_t newsize)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_ga9f3f999396c8f77ca5e80e7b40ac29e3"><div class="ttname"><a href="group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3">mi_heap_recalloc_aligned</a></div><div class="ttdeci">void * mi_heap_recalloc_aligned(mi_heap_t *heap, void *p, size_t newcount, size_t size, size_t alignment)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_gac90da54fa7e5d10bdc97ce0b51dce2eb"><div class="ttname"><a href="group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb">mi_heap_rezalloc_aligned_at</a></div><div class="ttdeci">void * mi_heap_rezalloc_aligned_at(mi_heap_t *heap, void *p, size_t newsize, size_t alignment, size_t offset)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_gacd71a7bce96aab38ae6de17af2eb2cf0"><div class="ttname"><a href="group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0">mi_rezalloc_aligned</a></div><div class="ttdeci">void * mi_rezalloc_aligned(void *p, size_t newsize, size_t alignment)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_gacfad83f14eb5d6a42a497a898e19fc76"><div class="ttname"><a href="group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76">mi_heap_rezalloc</a></div><div class="ttdeci">void * mi_heap_rezalloc(mi_heap_t *heap, void *p, size_t newsize)</div></div>
+<div class="ttc" id="agroup__zeroinit_html_gae8b358c417e61d5307da002702b0a8e1"><div class="ttname"><a href="group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1">mi_rezalloc_aligned_at</a></div><div class="ttdeci">void * mi_rezalloc_aligned_at(void *p, size_t newsize, size_t alignment, size_t offset)</div></div>
+</div><!-- fragment --></div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="navelem"><b>mimalloc-doc.h</b></li>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/mimalloc-doxygen.css b/extlib/mimalloc/docs/mimalloc-doxygen.css
new file mode 100644 (file)
index 0000000..b24f564
--- /dev/null
@@ -0,0 +1,49 @@
+#projectlogo img {
+       padding: 1ex;
+}
+tt, code, kbd, samp, div.memproto, div.fragment, div.line, table.memname {
+       font-family: Consolas, Monaco, Inconsolata, "Courier New", monospace;
+}
+.image img, .textblock img {
+       max-width: 99%;
+       max-height: 350px;
+}
+table.memname, .memname{
+       font-weight: bold;
+}
+code {
+       background-color: #EEE;
+       padding: 0ex 0.25ex;
+}
+body {
+       margin: 1ex 1ex 0ex 1ex;
+       border: 1px solid black;
+}
+.contents table, .contents div, .contents p, .contents dl {
+       font-size: 16px;
+       line-height: 1.44;
+}
+body #nav-tree .label {
+       font-size: 14px;
+}
+a{
+       text-decoration: underline;
+}
+#side-nav {
+       margin-left: 1ex;
+       border-left: 1px solid black;
+}
+#nav-tree {
+       padding-left: 1ex;
+}
+#nav-path {
+       display: none;
+}
+div.fragment {
+       background-color: #EEE;
+       padding: 0.25ex 0.5ex;
+       border-color: black;
+}
+#nav-sync img {
+       display: none;
+}
diff --git a/extlib/mimalloc/docs/mimalloc-logo.svg b/extlib/mimalloc/docs/mimalloc-logo.svg
new file mode 100644 (file)
index 0000000..672c7e4
--- /dev/null
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="20mm"
+   height="20mm"
+   viewBox="0 0 10 10"
+   version="1.1"
+   id="svg8"
+   sodipodi:docname="mimalloc-logo.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <defs
+     id="defs2">
+    <linearGradient
+       id="linearGradient6471"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#008da3;stop-opacity:1;"
+         offset="0"
+         id="stop6469" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="23.706667"
+     inkscape:cx="24.864771"
+     inkscape:cy="35.79485"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="3840"
+     inkscape:window-height="2050"
+     inkscape:window-x="-12"
+     inkscape:window-y="-12"
+     inkscape:window-maximized="1"
+     inkscape:snap-object-midpoints="false"
+     inkscape:snap-bbox="false"
+     inkscape:snap-bbox-midpoints="false"
+     inkscape:bbox-nodes="false"
+     inkscape:bbox-paths="false"
+     inkscape:snap-bbox-edge-midpoints="false"
+     showguides="false"
+     showborder="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid815"
+       units="mm"
+       spacingx="0.99999997"
+       spacingy="0.99999997" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-287)">
+    <circle
+       id="path840"
+       cx="5"
+       cy="292"
+       style="fill:#0d8ca4;fill-opacity:0.64444448;fill-rule:nonzero;stroke:#000000;stroke-width:0.56603777;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       r="4.7169809" />
+    <ellipse
+       id="path4522"
+       style="fill:none;stroke:#000000;stroke-width:0.6;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       cx="5.171"
+       cy="292"
+       r="4.8711185" />
+    <g
+       aria-label="malloc"
+       transform="matrix(0.9031136,0,0,0.80782132,0.58122269,37.023319)"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.28599727"
+       id="text6501">
+      <path
+         inkscape:connector-curvature="0"
+         d="m 1.7799307,318.87079 c 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.70159 c 0.013406,-0.0223 0.031281,-0.0469 0.05139,-0.0693 0.017875,-0.0223 0.049156,-0.0447 0.089374,-0.0693 0.040218,-0.0223 0.082671,-0.0358 0.1273581,-0.0358 0.040218,0 0.078202,0.0179 0.1117177,0.0536 0.031281,0.0358 0.049156,0.0827 0.049156,0.143 v 0.67924 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.67924 -0.0223 c 0.0067,-0.0112 0.01564,-0.0223 0.024578,-0.0358 0.00894,-0.0134 0.022344,-0.0268 0.040218,-0.0447 0.017875,-0.0179 0.03575,-0.0335 0.053624,-0.0469 0.017875,-0.0134 0.042453,-0.0246 0.069265,-0.0335 0.026812,-0.009 0.053625,-0.0134 0.080437,-0.0134 0.040218,0 0.078202,0.0179 0.1117177,0.0536 0.031281,0.0358 0.049156,0.0827 0.049156,0.143 v 0.67924 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 0.029047,0 0.053624,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.67924 c 0,-0.11396 -0.037984,-0.21003 -0.1094833,-0.29047 -0.073734,-0.0804 -0.1631078,-0.12066 -0.2658881,-0.12066 -0.073734,0 -0.1407643,0.0156 -0.1988575,0.0425 -0.058093,0.0268 -0.1094833,0.0626 -0.1541704,0.10725 -0.075968,-0.0983 -0.1720452,-0.14971 -0.290466,-0.14971 -0.1027802,0 -0.1943887,0.029 -0.2748255,0.0849 -0.00894,-0.0179 -0.022343,-0.0335 -0.040218,-0.0469 -0.017875,-0.0134 -0.037984,-0.0201 -0.060328,-0.0201 -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 0.96524 c 0,0.0313 0.00894,0.0559 0.031281,0.076 0.020109,0.0223 0.044687,0.0313 0.075968,0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6515" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 4.2824069,317.69105 c -0.01564,0 -0.029047,0.004 -0.042453,0.009 -0.013406,0.007 -0.026812,0.0156 -0.03575,0.0246 -0.00894,0.0112 -0.017875,0.0223 -0.022344,0.0335 -0.078202,-0.0559 -0.1631079,-0.0849 -0.2569507,-0.0849 -0.145233,0 -0.2658881,0.0626 -0.359731,0.18322 -0.093843,0.12066 -0.1407642,0.26366 -0.1407642,0.42453 0,0.16311 0.046921,0.30611 0.1407642,0.42676 0.093843,0.12066 0.214498,0.18098 0.359731,0.18098 0.093843,0 0.1787483,-0.0268 0.2569507,-0.0849 0.00894,0.0201 0.022344,0.0358 0.040218,0.0491 0.017875,0.0134 0.037984,0.0179 0.060328,0.0179 0.029047,0 0.053625,-0.009 0.075968,-0.0313 0.020109,-0.0201 0.031281,-0.0447 0.031281,-0.076 v -0.96524 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z m -0.107249,0.77979 c -0.017875,0.0424 -0.040218,0.0782 -0.067031,0.10948 -0.026812,0.0313 -0.055859,0.0559 -0.08714,0.0715 -0.031281,0.0156 -0.064796,0.0224 -0.096077,0.0224 -0.073734,0 -0.1407643,-0.0358 -0.1988575,-0.10949 -0.058093,-0.0737 -0.08714,-0.16757 -0.08714,-0.28376 0,-0.11395 0.029047,-0.2078 0.08714,-0.28153 0.058093,-0.0737 0.1251238,-0.11172 0.1988575,-0.11172 0.049156,0 0.098312,0.0179 0.1429986,0.0536 0.044687,0.0358 0.080437,0.0871 0.107249,0.1497 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6517" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 4.7471525,317.2263 c -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 1.21549 c 0,0.10502 0.0067,0.18545 0.022343,0.24131 0.00447,0.0268 0.017875,0.0469 0.037984,0.0603 0.017875,0.0134 0.040218,0.0201 0.064796,0.0201 0.00894,0 0.017875,0 0.026812,-0.002 0.00447,-0.002 0.011172,-0.004 0.017875,-0.009 0.0067,-0.002 0.013406,-0.004 0.017875,-0.009 0.00447,-0.004 0.011172,-0.009 0.01564,-0.0134 0.00447,-0.004 0.0067,-0.0112 0.011172,-0.0156 0.00447,-0.004 0.0067,-0.0112 0.00894,-0.0179 0.00223,-0.007 0.00447,-0.0134 0.0067,-0.0201 0,-0.007 0.00223,-0.0134 0.00223,-0.0201 v -0.007 c 0,-0.002 -0.00223,-0.004 -0.00223,-0.007 0,-0.002 0,-0.004 0,-0.009 -0.011172,-0.0447 -0.01564,-0.10725 -0.01564,-0.19216 v -1.21549 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6519" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 5.2655226,317.2263 c -0.031281,0 -0.055859,0.0112 -0.075968,0.0313 -0.022343,0.0223 -0.031281,0.0469 -0.031281,0.076 v 1.21549 c 0,0.10502 0.0067,0.18545 0.022344,0.24131 0.00447,0.0268 0.017875,0.0469 0.037984,0.0603 0.017875,0.0134 0.040218,0.0201 0.064796,0.0201 0.00894,0 0.017875,0 0.026812,-0.002 0.00447,-0.002 0.011172,-0.004 0.017875,-0.009 0.0067,-0.002 0.013406,-0.004 0.017875,-0.009 0.00447,-0.004 0.011172,-0.009 0.01564,-0.0134 0.00447,-0.004 0.0067,-0.0112 0.011172,-0.0156 0.00447,-0.004 0.0067,-0.0112 0.00894,-0.0179 0.00223,-0.007 0.00447,-0.0134 0.0067,-0.0201 0,-0.007 0.00223,-0.0134 0.00223,-0.0201 v -0.007 c 0,-0.002 -0.00223,-0.004 -0.00223,-0.007 0,-0.002 0,-0.004 0,-0.009 -0.011172,-0.0447 -0.01564,-0.10725 -0.01564,-0.19216 v -1.21549 c 0,-0.029 -0.011172,-0.0536 -0.031281,-0.076 -0.022343,-0.0201 -0.046921,-0.0313 -0.075968,-0.0313 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6521" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 6.6061344,318.28092 c 0,-0.16087 -0.049156,-0.30387 -0.1429986,-0.42453 -0.093843,-0.12065 -0.2144979,-0.18322 -0.3574966,-0.18322 -0.145233,0 -0.2658881,0.0626 -0.3597309,0.18322 -0.093843,0.12066 -0.1407643,0.26366 -0.1407643,0.42453 0,0.16311 0.046921,0.30611 0.1407643,0.42676 0.093843,0.12066 0.2144979,0.18098 0.3597309,0.18098 0.1429987,0 0.2636538,-0.0603 0.3574966,-0.18098 0.093843,-0.12065 0.1429986,-0.26365 0.1429986,-0.42676 z m -0.2144979,0 c 0,0.11619 -0.031281,0.21003 -0.089374,0.28376 -0.058093,0.0737 -0.1251238,0.10949 -0.1966231,0.10949 -0.073734,0 -0.1407643,-0.0358 -0.1988575,-0.10949 -0.058093,-0.0737 -0.08714,-0.16757 -0.08714,-0.28376 0,-0.11395 0.029047,-0.2078 0.08714,-0.28153 0.058093,-0.0737 0.1251238,-0.11172 0.1988575,-0.11172 0.071499,0 0.1385299,0.038 0.1966231,0.11172 0.058093,0.0737 0.089374,0.16758 0.089374,0.28153 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6523" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 7.6406407,318.47754 c -0.00894,-0.004 -0.01564,-0.007 -0.024578,-0.009 -0.00894,-0.002 -0.017875,-0.004 -0.026812,-0.004 -0.044687,0 -0.075968,0.0201 -0.093843,0.0559 -0.026812,0.0514 -0.060328,0.0894 -0.098312,0.11618 -0.040218,0.0268 -0.080437,0.038 -0.1206551,0.038 -0.071499,0 -0.1340612,-0.0358 -0.1921544,-0.10949 -0.058093,-0.0737 -0.084905,-0.16757 -0.084905,-0.28376 0,-0.11395 0.026812,-0.2078 0.084905,-0.28153 0.058093,-0.0737 0.1206551,-0.11172 0.1921544,-0.11172 0.080437,0 0.1474674,0.0447 0.2055606,0.1296 0.020109,0.0335 0.049156,0.0491 0.089374,0.0491 0.022343,0 0.040218,-0.004 0.058093,-0.0179 0.0067,-0.004 0.013406,-0.009 0.020109,-0.0156 0.0067,-0.007 0.011172,-0.0134 0.01564,-0.0224 0.00447,-0.009 0.0067,-0.0156 0.00894,-0.0246 0.00223,-0.009 0.00447,-0.0179 0.00447,-0.0268 0,-0.004 -0.00223,-0.0112 -0.00223,-0.0156 0,-0.004 -0.00223,-0.009 -0.00223,-0.0134 -0.00223,-0.004 -0.00447,-0.0112 -0.0067,-0.0156 -0.00223,-0.004 -0.00447,-0.009 -0.0067,-0.0134 -0.031281,-0.0447 -0.064796,-0.0827 -0.1027803,-0.11619 -0.037984,-0.0335 -0.080437,-0.0603 -0.1295925,-0.0804 -0.049156,-0.0201 -0.1005459,-0.0313 -0.1519361,-0.0313 -0.1429986,0 -0.2614194,0.0626 -0.3530279,0.18322 -0.093843,0.12066 -0.1385299,0.26366 -0.1385299,0.42453 0,0.16311 0.044687,0.30611 0.1385299,0.42676 0.091608,0.12066 0.2100293,0.18098 0.3530279,0.18098 0.084905,0 0.1631078,-0.0246 0.2346072,-0.0737 0.071499,-0.0492 0.1273581,-0.11172 0.1720452,-0.19215 0.0067,-0.0134 0.011172,-0.0313 0.013406,-0.0514 0,-0.0425 -0.020109,-0.0737 -0.055859,-0.0939 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
+         id="path6525" />
+    </g>
+    <g
+       aria-label="m"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+       id="text848">
+      <path
+         d="m 2.3718985,293.17081 c 0.080862,0 0.1492836,-0.0249 0.211485,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.95313 c 0.037321,-0.0622 0.087082,-0.13062 0.1430634,-0.19282 0.049761,-0.0622 0.1368433,-0.1244 0.2488059,-0.19283 0.1119627,-0.0622 0.2301455,-0.0995 0.3545485,-0.0995 0.1119626,0 0.2177051,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 -0.0622 c 0.018661,-0.0311 0.043541,-0.0622 0.068422,-0.0995 0.024881,-0.0373 0.062201,-0.0746 0.1119626,-0.1244 0.049761,-0.0498 0.099522,-0.0933 0.1492836,-0.13063 0.049761,-0.0373 0.1181828,-0.0684 0.1928246,-0.0933 0.074642,-0.0249 0.1492835,-0.0373 0.2239253,-0.0373 0.1119626,0 0.2177052,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 c 0,-0.31722 -0.1057425,-0.58469 -0.3047872,-0.80861 -0.2052649,-0.22393 -0.4540708,-0.33589 -0.7401976,-0.33589 -0.2052649,0 -0.3918693,0.0435 -0.5535932,0.11818 -0.1617238,0.0746 -0.3047872,0.17416 -0.4291902,0.29857 -0.211485,-0.27369 -0.4789514,-0.41675 -0.8086192,-0.41675 -0.2861268,0 -0.5411529,0.0809 -0.7650782,0.23636 -0.024881,-0.0498 -0.062202,-0.0933 -0.1119627,-0.13062 -0.049761,-0.0373 -0.1057425,-0.056 -0.167944,-0.056 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13062 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.1244029,0.0871 0.211485,0.0871 z"
+         style="stroke-width:0.15923578"
+         id="path834" />
+    </g>
+    <g
+       id="g28"
+       transform="translate(-0.23995531,0.02790178)">
+      <g
+         id="g835">
+        <g
+           transform="matrix(1.0000001,0,0,0.98554676,-7.6075554e-7,4.2369817)"
+           id="g25">
+          <path
+             d="m 7.426334,293.15097 c 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21149 v -2.6871 c 0,-0.0809 -0.031101,-0.14928 -0.087082,-0.21149 -0.062201,-0.056 -0.1306232,-0.0871 -0.2114851,-0.0871 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13063 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.15551 0.087082,0.21149 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 z"
+             style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+             id="path896"
+             inkscape:connector-curvature="0" />
+        </g>
+        <path
+           d="m 7.4249389,289.61754 c 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.086228,-0.1244 0.087082,-0.21149 l 0.0014,-0.14231 c 7.93e-4,-0.0809 -0.031101,-0.14929 -0.087082,-0.21149 -0.062201,-0.056 -0.1306232,-0.0871 -0.2114851,-0.0871 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.086289,0.13062 -0.087082,0.21149 l -0.0014,0.14231 c -8.538e-4,0.0871 0.024881,0.15551 0.087082,0.21149 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 z"
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
+           id="path898"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="scsscscsscs" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/extlib/mimalloc/docs/modules.html b/extlib/mimalloc/docs/modules.html
new file mode 100644 (file)
index 0000000..7457cb9
--- /dev/null
@@ -0,0 +1,124 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Modules</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('modules.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Modules</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all modules:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__malloc.html" target="_self">Basic Allocation</a></td><td class="desc">The basic allocation interface </td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__extended.html" target="_self">Extended Functions</a></td><td class="desc">Extended functionality </td></tr>
+<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__aligned.html" target="_self">Aligned Allocation</a></td><td class="desc">Allocating aligned memory blocks </td></tr>
+<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__heap.html" target="_self">Heap Allocation</a></td><td class="desc">First-class heaps that can be destroyed in one go </td></tr>
+<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__zeroinit.html" target="_self">Zero initialized re-allocation</a></td><td class="desc">The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too </td></tr>
+<tr id="row_5_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__typed.html" target="_self">Typed Macros</a></td><td class="desc">Typed allocation macros </td></tr>
+<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__analysis.html" target="_self">Heap Introspection</a></td><td class="desc">Inspect the heap at runtime </td></tr>
+<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__options.html" target="_self">Runtime Options</a></td><td class="desc">Set runtime behavior </td></tr>
+<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__posix.html" target="_self">Posix</a></td><td class="desc"><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions </td></tr>
+<tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__cpp.html" target="_self">C++ wrappers</a></td><td class="desc"><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure </td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/modules.js b/extlib/mimalloc/docs/modules.js
new file mode 100644 (file)
index 0000000..b2c2a22
--- /dev/null
@@ -0,0 +1,13 @@
+var modules =
+[
+    [ "Basic Allocation", "group__malloc.html", "group__malloc" ],
+    [ "Extended Functions", "group__extended.html", "group__extended" ],
+    [ "Aligned Allocation", "group__aligned.html", "group__aligned" ],
+    [ "Heap Allocation", "group__heap.html", "group__heap" ],
+    [ "Zero initialized re-allocation", "group__zeroinit.html", "group__zeroinit" ],
+    [ "Typed Macros", "group__typed.html", "group__typed" ],
+    [ "Heap Introspection", "group__analysis.html", "group__analysis" ],
+    [ "Runtime Options", "group__options.html", "group__options" ],
+    [ "Posix", "group__posix.html", "group__posix" ],
+    [ "C++ wrappers", "group__cpp.html", "group__cpp" ]
+];
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/nav_f.png b/extlib/mimalloc/docs/nav_f.png
new file mode 100644 (file)
index 0000000..cbfef42
Binary files /dev/null and b/extlib/mimalloc/docs/nav_f.png differ
diff --git a/extlib/mimalloc/docs/nav_g.png b/extlib/mimalloc/docs/nav_g.png
new file mode 100644 (file)
index 0000000..2093a23
Binary files /dev/null and b/extlib/mimalloc/docs/nav_g.png differ
diff --git a/extlib/mimalloc/docs/nav_h.png b/extlib/mimalloc/docs/nav_h.png
new file mode 100644 (file)
index 0000000..9fc5ada
Binary files /dev/null and b/extlib/mimalloc/docs/nav_h.png differ
diff --git a/extlib/mimalloc/docs/navtree.css b/extlib/mimalloc/docs/navtree.css
new file mode 100644 (file)
index 0000000..046366c
--- /dev/null
@@ -0,0 +1,146 @@
+#nav-tree .children_ul {
+  margin:0;
+  padding:4px;
+}
+
+#nav-tree ul {
+  list-style:none outside none;
+  margin:0px;
+  padding:0px;
+}
+
+#nav-tree li {
+  white-space:nowrap;
+  margin:0px;
+  padding:0px;
+}
+
+#nav-tree .plus {
+  margin:0px;
+}
+
+#nav-tree .selected {
+  background-image: url('tab_a.png');
+  background-repeat:repeat-x;
+  color: #fff;
+  text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
+}
+
+#nav-tree img {
+  margin:0px;
+  padding:0px;
+  border:0px;
+  vertical-align: middle;
+}
+
+#nav-tree a {
+  text-decoration:none;
+  padding:0px;
+  margin:0px;
+  outline:none;
+}
+
+#nav-tree .label {
+  margin:0px;
+  padding:0px;
+  font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+}
+
+#nav-tree .label a {
+  padding:2px;
+}
+
+#nav-tree .selected a {
+  text-decoration:none;
+  color:#fff;
+}
+
+#nav-tree .children_ul {
+  margin:0px;
+  padding:0px;
+}
+
+#nav-tree .item {
+  margin:0px;
+  padding:0px;
+}
+
+#nav-tree {
+  padding: 0px 0px;
+  background-color: #FAFAFF; 
+  font-size:14px;
+  overflow:auto;
+}
+
+#doc-content {
+  overflow:auto;
+  display:block;
+  padding:0px;
+  margin:0px;
+  -webkit-overflow-scrolling : touch; /* iOS 5+ */
+}
+
+#side-nav {
+  padding:0 6px 0 0;
+  margin: 0px;
+  display:block;
+  position: absolute;
+  left: 0px;
+  width: 180px;
+}
+
+.ui-resizable .ui-resizable-handle {
+  display:block;
+}
+
+.ui-resizable-e {
+  background-image:url("splitbar.png");
+  background-size:100%;
+  background-repeat:repeat-y;
+  background-attachment: scroll;
+  cursor:ew-resize;
+  height:100%;
+  right:0;
+  top:0;
+  width:6px;
+}
+
+.ui-resizable-handle {
+  display:none;
+  font-size:0.1px;
+  position:absolute;
+  z-index:1;
+}
+
+#nav-tree-contents {
+  margin: 6px 0px 0px 0px;
+}
+
+#nav-tree {
+  background-image:url('nav_h.png');
+  background-repeat:repeat-x;
+  background-color: #F2F3F3;
+  -webkit-overflow-scrolling : touch; /* iOS 5+ */
+}
+
+#nav-sync {
+  position:absolute;
+  top:5px;
+  right:24px;
+  z-index:0;
+}
+
+#nav-sync img {
+  opacity:0.3;
+}
+
+#nav-sync img:hover {
+  opacity:0.9;
+}
+
+@media print
+{
+  #nav-tree { display: none; }
+  div.ui-resizable-handle { display: none; position: relative; }
+}
+
diff --git a/extlib/mimalloc/docs/navtree.js b/extlib/mimalloc/docs/navtree.js
new file mode 100644 (file)
index 0000000..1e272d3
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ @licstart  The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend  The above is the entire license notice for the JavaScript code in this file
+ */
+var navTreeSubIndices = new Array();
+var arrowDown = '&#9660;';
+var arrowRight = '&#9658;';
+
+function getData(varName)
+{
+  var i = varName.lastIndexOf('/');
+  var n = i>=0 ? varName.substring(i+1) : varName;
+  return eval(n.replace(/\-/g,'_'));
+}
+
+function stripPath(uri)
+{
+  return uri.substring(uri.lastIndexOf('/')+1);
+}
+
+function stripPath2(uri)
+{
+  var i = uri.lastIndexOf('/');
+  var s = uri.substring(i+1);
+  var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/);
+  return m ? uri.substring(i-6) : s;
+}
+
+function hashValue()
+{
+  return $(location).attr('hash').substring(1).replace(/[^\w\-]/g,'');
+}
+
+function hashUrl()
+{
+  return '#'+hashValue();
+}
+
+function pathName()
+{
+  return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]/g, '');
+}
+
+function localStorageSupported()
+{
+  try {
+    return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem;
+  }
+  catch(e) {
+    return false;
+  }
+}
+
+function storeLink(link)
+{
+  if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) {
+      window.localStorage.setItem('navpath',link);
+  }
+}
+
+function deleteLink()
+{
+  if (localStorageSupported()) {
+    window.localStorage.setItem('navpath','');
+  }
+}
+
+function cachedLink()
+{
+  if (localStorageSupported()) {
+    return window.localStorage.getItem('navpath');
+  } else {
+    return '';
+  }
+}
+
+function getScript(scriptName,func,show)
+{
+  var head = document.getElementsByTagName("head")[0];
+  var script = document.createElement('script');
+  script.id = scriptName;
+  script.type = 'text/javascript';
+  script.onload = func;
+  script.src = scriptName+'.js';
+  head.appendChild(script);
+}
+
+function createIndent(o,domNode,node,level)
+{
+  var level=-1;
+  var n = node;
+  while (n.parentNode) { level++; n=n.parentNode; }
+  if (node.childrenData) {
+    var imgNode = document.createElement("span");
+    imgNode.className = 'arrow';
+    imgNode.style.paddingLeft=(16*level).toString()+'px';
+    imgNode.innerHTML=arrowRight;
+    node.plus_img = imgNode;
+    node.expandToggle = document.createElement("a");
+    node.expandToggle.href = "javascript:void(0)";
+    node.expandToggle.onclick = function() {
+      if (node.expanded) {
+        $(node.getChildrenUL()).slideUp("fast");
+        node.plus_img.innerHTML=arrowRight;
+        node.expanded = false;
+      } else {
+        expandNode(o, node, false, false);
+      }
+    }
+    node.expandToggle.appendChild(imgNode);
+    domNode.appendChild(node.expandToggle);
+  } else {
+    var span = document.createElement("span");
+    span.className = 'arrow';
+    span.style.width   = 16*(level+1)+'px';
+    span.innerHTML = '&#160;';
+    domNode.appendChild(span);
+  }
+}
+
+var animationInProgress = false;
+
+function gotoAnchor(anchor,aname,updateLocation)
+{
+  var pos, docContent = $('#doc-content');
+  var ancParent = $(anchor.parent());
+  if (ancParent.hasClass('memItemLeft') ||
+      ancParent.hasClass('memtitle') ||
+      ancParent.hasClass('fieldname') ||
+      ancParent.hasClass('fieldtype') ||
+      ancParent.is(':header'))
+  {
+    pos = ancParent.position().top;
+  } else if (anchor.position()) {
+    pos = anchor.position().top;
+  }
+  if (pos) {
+    var dist = Math.abs(Math.min(
+               pos-docContent.offset().top,
+               docContent[0].scrollHeight-
+               docContent.height()-docContent.scrollTop()));
+    animationInProgress=true;
+    docContent.animate({
+      scrollTop: pos + docContent.scrollTop() - docContent.offset().top
+    },Math.max(50,Math.min(500,dist)),function(){
+      if (updateLocation) window.location.href=aname;
+      animationInProgress=false;
+    });
+  }
+}
+
+function newNode(o, po, text, link, childrenData, lastNode)
+{
+  var node = new Object();
+  node.children = Array();
+  node.childrenData = childrenData;
+  node.depth = po.depth + 1;
+  node.relpath = po.relpath;
+  node.isLast = lastNode;
+
+  node.li = document.createElement("li");
+  po.getChildrenUL().appendChild(node.li);
+  node.parentNode = po;
+
+  node.itemDiv = document.createElement("div");
+  node.itemDiv.className = "item";
+
+  node.labelSpan = document.createElement("span");
+  node.labelSpan.className = "label";
+
+  createIndent(o,node.itemDiv,node,0);
+  node.itemDiv.appendChild(node.labelSpan);
+  node.li.appendChild(node.itemDiv);
+
+  var a = document.createElement("a");
+  node.labelSpan.appendChild(a);
+  node.label = document.createTextNode(text);
+  node.expanded = false;
+  a.appendChild(node.label);
+  if (link) {
+    var url;
+    if (link.substring(0,1)=='^') {
+      url = link.substring(1);
+      link = url;
+    } else {
+      url = node.relpath+link;
+    }
+    a.className = stripPath(link.replace('#',':'));
+    if (link.indexOf('#')!=-1) {
+      var aname = '#'+link.split('#')[1];
+      var srcPage = stripPath(pathName());
+      var targetPage = stripPath(link.split('#')[0]);
+      a.href = srcPage!=targetPage ? url : "javascript:void(0)";
+      a.onclick = function(){
+        storeLink(link);
+        if (!$(a).parent().parent().hasClass('selected'))
+        {
+          $('.item').removeClass('selected');
+          $('.item').removeAttr('id');
+          $(a).parent().parent().addClass('selected');
+          $(a).parent().parent().attr('id','selected');
+        }
+        var anchor = $(aname);
+        gotoAnchor(anchor,aname,true);
+      };
+    } else {
+      a.href = url;
+      a.onclick = function() { storeLink(link); }
+    }
+  } else {
+    if (childrenData != null)
+    {
+      a.className = "nolink";
+      a.href = "javascript:void(0)";
+      a.onclick = node.expandToggle.onclick;
+    }
+  }
+
+  node.childrenUL = null;
+  node.getChildrenUL = function() {
+    if (!node.childrenUL) {
+      node.childrenUL = document.createElement("ul");
+      node.childrenUL.className = "children_ul";
+      node.childrenUL.style.display = "none";
+      node.li.appendChild(node.childrenUL);
+    }
+    return node.childrenUL;
+  };
+
+  return node;
+}
+
+function showRoot()
+{
+  var headerHeight = $("#top").height();
+  var footerHeight = $("#nav-path").height();
+  var windowHeight = $(window).height() - headerHeight - footerHeight;
+  (function (){ // retry until we can scroll to the selected item
+    try {
+      var navtree=$('#nav-tree');
+      navtree.scrollTo('#selected',100,{offset:-windowHeight/2});
+    } catch (err) {
+      setTimeout(arguments.callee, 0);
+    }
+  })();
+}
+
+function expandNode(o, node, imm, showRoot)
+{
+  if (node.childrenData && !node.expanded) {
+    if (typeof(node.childrenData)==='string') {
+      var varName    = node.childrenData;
+      getScript(node.relpath+varName,function(){
+        node.childrenData = getData(varName);
+        expandNode(o, node, imm, showRoot);
+      }, showRoot);
+    } else {
+      if (!node.childrenVisited) {
+        getNode(o, node);
+      }
+      $(node.getChildrenUL()).slideDown("fast");
+      node.plus_img.innerHTML = arrowDown;
+      node.expanded = true;
+    }
+  }
+}
+
+function glowEffect(n,duration)
+{
+  n.addClass('glow').delay(duration).queue(function(next){
+    $(this).removeClass('glow');next();
+  });
+}
+
+function highlightAnchor()
+{
+  var aname = hashUrl();
+  var anchor = $(aname);
+  if (anchor.parent().attr('class')=='memItemLeft'){
+    var rows = $('.memberdecls tr[class$="'+hashValue()+'"]');
+    glowEffect(rows.children(),300); // member without details
+  } else if (anchor.parent().attr('class')=='fieldname'){
+    glowEffect(anchor.parent().parent(),1000); // enum value
+  } else if (anchor.parent().attr('class')=='fieldtype'){
+    glowEffect(anchor.parent().parent(),1000); // struct field
+  } else if (anchor.parent().is(":header")) {
+    glowEffect(anchor.parent(),1000); // section header
+  } else {
+    glowEffect(anchor.next(),1000); // normal member
+  }
+}
+
+function selectAndHighlight(hash,n)
+{
+  var a;
+  if (hash) {
+    var link=stripPath(pathName())+':'+hash.substring(1);
+    a=$('.item a[class$="'+link+'"]');
+  }
+  if (a && a.length) {
+    a.parent().parent().addClass('selected');
+    a.parent().parent().attr('id','selected');
+    highlightAnchor();
+  } else if (n) {
+    $(n.itemDiv).addClass('selected');
+    $(n.itemDiv).attr('id','selected');
+  }
+  if ($('#nav-tree-contents .item:first').hasClass('selected')) {
+    $('#nav-sync').css('top','30px');
+  } else {
+    $('#nav-sync').css('top','5px');
+  }
+  showRoot();
+}
+
+function showNode(o, node, index, hash)
+{
+  if (node && node.childrenData) {
+    if (typeof(node.childrenData)==='string') {
+      var varName    = node.childrenData;
+      getScript(node.relpath+varName,function(){
+        node.childrenData = getData(varName);
+        showNode(o,node,index,hash);
+      },true);
+    } else {
+      if (!node.childrenVisited) {
+        getNode(o, node);
+      }
+      $(node.getChildrenUL()).css({'display':'block'});
+      node.plus_img.innerHTML = arrowDown;
+      node.expanded = true;
+      var n = node.children[o.breadcrumbs[index]];
+      if (index+1<o.breadcrumbs.length) {
+        showNode(o,n,index+1,hash);
+      } else {
+        if (typeof(n.childrenData)==='string') {
+          var varName = n.childrenData;
+          getScript(n.relpath+varName,function(){
+            n.childrenData = getData(varName);
+            node.expanded=false;
+            showNode(o,node,index,hash); // retry with child node expanded
+          },true);
+        } else {
+          var rootBase = stripPath(o.toroot.replace(/\..+$/, ''));
+          if (rootBase=="index" || rootBase=="pages" || rootBase=="search") {
+            expandNode(o, n, true, true);
+          }
+          selectAndHighlight(hash,n);
+        }
+      }
+    }
+  } else {
+    selectAndHighlight(hash);
+  }
+}
+
+function removeToInsertLater(element) {
+  var parentNode = element.parentNode;
+  var nextSibling = element.nextSibling;
+  parentNode.removeChild(element);
+  return function() {
+    if (nextSibling) {
+      parentNode.insertBefore(element, nextSibling);
+    } else {
+      parentNode.appendChild(element);
+    }
+  };
+}
+
+function getNode(o, po)
+{
+  var insertFunction = removeToInsertLater(po.li);
+  po.childrenVisited = true;
+  var l = po.childrenData.length-1;
+  for (var i in po.childrenData) {
+    var nodeData = po.childrenData[i];
+    po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2],
+      i==l);
+  }
+  insertFunction();
+}
+
+function gotoNode(o,subIndex,root,hash,relpath)
+{
+  var nti = navTreeSubIndices[subIndex][root+hash];
+  o.breadcrumbs = $.extend(true, [], nti ? nti : navTreeSubIndices[subIndex][root]);
+  if (!o.breadcrumbs && root!=NAVTREE[0][1]) { // fallback: show index
+    navTo(o,NAVTREE[0][1],"",relpath);
+    $('.item').removeClass('selected');
+    $('.item').removeAttr('id');
+  }
+  if (o.breadcrumbs) {
+    o.breadcrumbs.unshift(0); // add 0 for root node
+    showNode(o, o.node, 0, hash);
+  }
+}
+
+function navTo(o,root,hash,relpath)
+{
+  var link = cachedLink();
+  if (link) {
+    var parts = link.split('#');
+    root = parts[0];
+    if (parts.length>1) hash = '#'+parts[1].replace(/[^\w\-]/g,'');
+    else hash='';
+  }
+  if (hash.match(/^#l\d+$/)) {
+    var anchor=$('a[name='+hash.substring(1)+']');
+    glowEffect(anchor.parent(),1000); // line number
+    hash=''; // strip line number anchors
+  }
+  var url=root+hash;
+  var i=-1;
+  while (NAVTREEINDEX[i+1]<=url) i++;
+  if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index
+  if (navTreeSubIndices[i]) {
+    gotoNode(o,i,root,hash,relpath)
+  } else {
+    getScript(relpath+'navtreeindex'+i,function(){
+      navTreeSubIndices[i] = eval('NAVTREEINDEX'+i);
+      if (navTreeSubIndices[i]) {
+        gotoNode(o,i,root,hash,relpath);
+      }
+    },true);
+  }
+}
+
+function showSyncOff(n,relpath)
+{
+    n.html('<img src="'+relpath+'sync_off.png" title="'+SYNCOFFMSG+'"/>');
+}
+
+function showSyncOn(n,relpath)
+{
+    n.html('<img src="'+relpath+'sync_on.png" title="'+SYNCONMSG+'"/>');
+}
+
+function toggleSyncButton(relpath)
+{
+  var navSync = $('#nav-sync');
+  if (navSync.hasClass('sync')) {
+    navSync.removeClass('sync');
+    showSyncOff(navSync,relpath);
+    storeLink(stripPath2(pathName())+hashUrl());
+  } else {
+    navSync.addClass('sync');
+    showSyncOn(navSync,relpath);
+    deleteLink();
+  }
+}
+
+var loadTriggered = false;
+var readyTriggered = false;
+var loadObject,loadToRoot,loadUrl,loadRelPath;
+
+$(window).on('load',function(){
+  if (readyTriggered) { // ready first
+    navTo(loadObject,loadToRoot,loadUrl,loadRelPath);
+    showRoot();
+  }
+  loadTriggered=true;
+});
+
+function initNavTree(toroot,relpath)
+{
+  var o = new Object();
+  o.toroot = toroot;
+  o.node = new Object();
+  o.node.li = document.getElementById("nav-tree-contents");
+  o.node.childrenData = NAVTREE;
+  o.node.children = new Array();
+  o.node.childrenUL = document.createElement("ul");
+  o.node.getChildrenUL = function() { return o.node.childrenUL; };
+  o.node.li.appendChild(o.node.childrenUL);
+  o.node.depth = 0;
+  o.node.relpath = relpath;
+  o.node.expanded = false;
+  o.node.isLast = true;
+  o.node.plus_img = document.createElement("span");
+  o.node.plus_img.className = 'arrow';
+  o.node.plus_img.innerHTML = arrowRight;
+
+  if (localStorageSupported()) {
+    var navSync = $('#nav-sync');
+    if (cachedLink()) {
+      showSyncOff(navSync,relpath);
+      navSync.removeClass('sync');
+    } else {
+      showSyncOn(navSync,relpath);
+    }
+    navSync.click(function(){ toggleSyncButton(relpath); });
+  }
+
+  if (loadTriggered) { // load before ready
+    navTo(o,toroot,hashUrl(),relpath);
+    showRoot();
+  } else { // ready before load
+    loadObject  = o;
+    loadToRoot  = toroot;
+    loadUrl     = hashUrl();
+    loadRelPath = relpath;
+    readyTriggered=true;
+  }
+
+  $(window).bind('hashchange', function(){
+     if (window.location.hash && window.location.hash.length>1){
+       var a;
+       if ($(location).attr('hash')){
+         var clslink=stripPath(pathName())+':'+hashValue();
+         a=$('.item a[class$="'+clslink.replace(/</g,'\\3c ')+'"]');
+       }
+       if (a==null || !$(a).parent().parent().hasClass('selected')){
+         $('.item').removeClass('selected');
+         $('.item').removeAttr('id');
+       }
+       var link=stripPath2(pathName());
+       navTo(o,link,hashUrl(),relpath);
+     } else if (!animationInProgress) {
+       $('#doc-content').scrollTop(0);
+       $('.item').removeClass('selected');
+       $('.item').removeAttr('id');
+       navTo(o,toroot,hashUrl(),relpath);
+     }
+  })
+}
+/* @license-end */
diff --git a/extlib/mimalloc/docs/navtreedata.js b/extlib/mimalloc/docs/navtreedata.js
new file mode 100644 (file)
index 0000000..8dd5a55
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ @licstart  The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend  The above is the entire license notice for the JavaScript code in this file
+*/
+var NAVTREE =
+[
+  [ "mi-malloc", "index.html", [
+    [ "Building", "build.html", null ],
+    [ "Using the library", "using.html", null ],
+    [ "Environment Options", "environment.html", null ],
+    [ "Overriding Malloc", "overrides.html", null ],
+    [ "Performance", "bench.html", null ],
+    [ "Modules", "modules.html", "modules" ],
+    [ "Data Structures", "annotated.html", [
+      [ "Data Structures", "annotated.html", "annotated_dup" ],
+      [ "Data Structure Index", "classes.html", null ],
+      [ "Data Fields", "functions.html", [
+        [ "All", "functions.html", null ],
+        [ "Variables", "functions_vars.html", null ]
+      ] ]
+    ] ]
+  ] ]
+];
+
+var NAVTREEINDEX =
+[
+"annotated.html"
+];
+
+var SYNCONMSG = 'click to disable panel synchronisation';
+var SYNCOFFMSG = 'click to enable panel synchronisation';
\ No newline at end of file
diff --git a/extlib/mimalloc/docs/navtreeindex0.js b/extlib/mimalloc/docs/navtreeindex0.js
new file mode 100644 (file)
index 0000000..7218170
--- /dev/null
@@ -0,0 +1,181 @@
+var NAVTREEINDEX0 =
+{
+"annotated.html":[6,0],
+"bench.html":[4],
+"build.html":[0],
+"classes.html":[6,1],
+"environment.html":[2],
+"functions.html":[6,2,0],
+"functions_vars.html":[6,2,1],
+"group__aligned.html":[5,2],
+"group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3":[5,2,2],
+"group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819":[5,2,7],
+"group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae":[5,2,5],
+"group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9":[5,2,1],
+"group__aligned.html#ga5850da130c936bd77db039dcfbc8295d":[5,2,4],
+"group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8":[5,2,8],
+"group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56":[5,2,3],
+"group__aligned.html#ga83c03016066b438f51a8095e9140be06":[5,2,0],
+"group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb":[5,2,6],
+"group__analysis.html":[5,6],
+"group__analysis.html#a332a6c14d736a99699d5453a1cb04b41":[5,6,0,0],
+"group__analysis.html#ab47526df656d8837ec3e97f11b83f835":[5,6,0,2],
+"group__analysis.html#ab820302c5cd0df133eb8e51650a008b4":[5,6,0,4],
+"group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8":[5,6,0,1],
+"group__analysis.html#ae848a3e6840414891035423948ca0383":[5,6,0,3],
+"group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377":[5,6,3],
+"group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5":[5,6,2],
+"group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed":[5,6,5],
+"group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af":[5,6,4],
+"group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65":[5,6,1],
+"group__analysis.html#structmi__heap__area__t":[5,6,0],
+"group__cpp.html":[5,9],
+"group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907":[5,9,7],
+"group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e":[5,9,6],
+"group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545":[5,9,1],
+"group__cpp.html#gab5e29558926d934c3f1cae8c815f942c":[5,9,3],
+"group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81":[5,9,4],
+"group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a":[5,9,5],
+"group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3":[5,9,2],
+"group__cpp.html#structmi__stl__allocator":[5,9,0],
+"group__extended.html":[5,1],
+"group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767":[5,1,16],
+"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,24],
+"group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,21],
+"group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[5,1,0],
+"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,25],
+"group__extended.html#ga251d369cda3f1c2a955c555486ed90e5":[5,1,2],
+"group__extended.html#ga299dae78d25ce112e384a98b7309c5be":[5,1,1],
+"group__extended.html#ga2d126e5c62d3badc35445e5d84166df2":[5,1,18],
+"group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50":[5,1,15],
+"group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece":[5,1,11],
+"group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,20],
+"group__extended.html#ga421430e2226d7d468529cec457396756":[5,1,4],
+"group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf":[5,1,9],
+"group__extended.html#ga537f13b299ddf801e49a5a94fde02c79":[5,1,19],
+"group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6":[5,1,6],
+"group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[5,1,8],
+"group__extended.html#ga7795a13d20087447281858d2c771cca1":[5,1,14],
+"group__extended.html#ga7d862c2affd5790381da14eb102a364d":[5,1,10],
+"group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,17],
+"group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45":[5,1,12],
+"group__extended.html#gaad25050b19f30cd79397b227e0157a3f":[5,1,7],
+"group__extended.html#gab1dac8476c46cb9eecab767eb40c1525":[5,1,23],
+"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[5,1,5],
+"group__extended.html#gad823d23444a4b77a40f66bf075a98a0c":[5,1,3],
+"group__extended.html#gae5b17ff027cd2150b43a33040250cf3f":[5,1,13],
+"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,22],
+"group__heap.html":[5,3],
+"group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[5,3,20],
+"group__heap.html#ga08ca6419a5c057a4d965868998eef487":[5,3,3],
+"group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5":[5,3,22],
+"group__heap.html#ga23acd7680fb0976dde3783254c6c874b":[5,3,11],
+"group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409":[5,3,5],
+"group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2":[5,3,0],
+"group__heap.html#ga45fb43a62776fbebbdf1edd99b527954":[5,3,26],
+"group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527":[5,3,18],
+"group__heap.html#ga4af03a6e2b93fae77424d93f889705c3":[5,3,2],
+"group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc":[5,3,7],
+"group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11":[5,3,14],
+"group__heap.html#ga7922f7495cde30b1984d0e6072419298":[5,3,4],
+"group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0":[5,3,13],
+"group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05":[5,3,8],
+"group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a":[5,3,23],
+"group__heap.html#ga903104592c8ed53417a3762da6241133":[5,3,24],
+"group__heap.html#ga9cbed01e42c0647907295de92c3fa296":[5,3,9],
+"group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d":[5,3,6],
+"group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368":[5,3,12],
+"group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0":[5,3,25],
+"group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55":[5,3,1],
+"group__heap.html#gaaef3395f66be48f37bdc8322509c5d81":[5,3,15],
+"group__heap.html#gab5b87e1805306f70df38789fcfcf6653":[5,3,10],
+"group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422":[5,3,21],
+"group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8":[5,3,19],
+"group__heap.html#gaf96c788a1bf553fe2d371de9365e047c":[5,3,17],
+"group__heap.html#gafc603b696bd14cae6da28658f950d98c":[5,3,16],
+"group__malloc.html":[5,0],
+"group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe":[5,0,8],
+"group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6":[5,0,4],
+"group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc":[5,0,9],
+"group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a":[5,0,3],
+"group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853":[5,0,7],
+"group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d":[5,0,0],
+"group__malloc.html#gaaabf971c2571891433477e2d21a35266":[5,0,11],
+"group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4":[5,0,1],
+"group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2":[5,0,10],
+"group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6":[5,0,5],
+"group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95":[5,0,2],
+"group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000":[5,0,12],
+"group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0":[5,0,6],
+"group__options.html":[5,7],
+"group__options.html#ga04180ae41b0d601421dd62ced40ca050":[5,7,2],
+"group__options.html#ga459ad98f18b3fc9275474807fe0ca188":[5,7,4],
+"group__options.html#ga65518b69ec5d32336b50e07f74b3f629":[5,7,8],
+"group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a":[5,7,3],
+"group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90":[5,7,6],
+"group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed":[5,7,7],
+"group__options.html#gaebf6ff707a2e688ebb1a2296ca564054":[5,7,1],
+"group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[5,7,5],
+"group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[5,7,0],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[5,7,0,1],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74":[5,7,0,12],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5":[5,7,0,11],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,14],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[5,7,0,3],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,8],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[5,7,0,4],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[5,7,0,5],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,15],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,16],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[5,7,0,2],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c":[5,7,0,7],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,13],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2":[5,7,0,6],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,9],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,10],
+"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[5,7,0,0],
+"group__posix.html":[5,8],
+"group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[5,8,7],
+"group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[5,8,3],
+"group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[5,8,1],
+"group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[5,8,6],
+"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,12],
+"group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[5,8,2],
+"group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[5,8,5],
+"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,13],
+"group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5":[5,8,11],
+"group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[5,8,8],
+"group__posix.html#gacff84f226ba9feb2031b8992e5579447":[5,8,9],
+"group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[5,8,0],
+"group__posix.html#gae01389eedab8d67341ff52e2aad80ebb":[5,8,4],
+"group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e":[5,8,10],
+"group__typed.html":[5,5],
+"group__typed.html#ga0619a62c5fd886f1016030abe91f0557":[5,5,7],
+"group__typed.html#ga1158b49a55dfa81f58a4426a7578f523":[5,5,9],
+"group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e":[5,5,5],
+"group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74":[5,5,1],
+"group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7":[5,5,2],
+"group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83":[5,5,3],
+"group__typed.html#gac77a61bdaf680a803785fe307820b48c":[5,5,10],
+"group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe":[5,5,6],
+"group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b":[5,5,8],
+"group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07":[5,5,0],
+"group__typed.html#gaf213d5422ec35e7f6caad827c79bc948":[5,5,4],
+"group__zeroinit.html":[5,4],
+"group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664":[5,4,4],
+"group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f":[5,4,6],
+"group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7":[5,4,2],
+"group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9":[5,4,7],
+"group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd":[5,4,0],
+"group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6":[5,4,8],
+"group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3":[5,4,1],
+"group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb":[5,4,5],
+"group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0":[5,4,9],
+"group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76":[5,4,3],
+"group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1":[5,4,10],
+"index.html":[],
+"modules.html":[5],
+"overrides.html":[3],
+"pages.html":[],
+"using.html":[1]
+};
diff --git a/extlib/mimalloc/docs/open.png b/extlib/mimalloc/docs/open.png
new file mode 100644 (file)
index 0000000..df440d1
Binary files /dev/null and b/extlib/mimalloc/docs/open.png differ
diff --git a/extlib/mimalloc/docs/overrides.html b/extlib/mimalloc/docs/overrides.html
new file mode 100644 (file)
index 0000000..fc0ad59
--- /dev/null
@@ -0,0 +1,198 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Overriding Malloc</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('overrides.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Overriding Malloc </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Overriding the standard <code>malloc</code> can be done either <em>dynamically</em> or <em>statically</em>.</p>
+<h2>Dynamic override</h2>
+<p>This is the recommended way to override the standard malloc interface.</p>
+<h3>Linux, BSD</h3>
+<p>On these systems we preload the mimalloc shared library so all calls to the standard <code>malloc</code> interface are resolved to the <em>mimalloc</em> library.</p>
+<ul>
+<li><code>env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram</code></li>
+</ul>
+<p>You can set extra environment variables to check that mimalloc is running, like: </p><div class="fragment"><div class="line">env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram</div>
+</div><!-- fragment --><p> or run with the debug version to get detailed statistics: </p><div class="fragment"><div class="line">env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram</div>
+</div><!-- fragment --><h3>MacOS</h3>
+<p>On macOS we can also preload the mimalloc shared library so all calls to the standard <code>malloc</code> interface are resolved to the <em>mimalloc</em> library.</p>
+<ul>
+<li><code>env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram</code></li>
+</ul>
+<p>Note that certain security restrictions may apply when doing this from the <a href="https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash">shell</a>.</p>
+<p>(Note: macOS support for dynamic overriding is recent, please report any issues.)</p>
+<h3>Windows</h3>
+<p>Overriding on Windows is robust and has the particular advantage to be able to redirect all malloc/free calls that go through the (dynamic) C runtime allocator, including those from other DLL's or libraries.</p>
+<p>The overriding on Windows requires that you link your program explicitly with the mimalloc DLL and use the C-runtime library as a DLL (using the <code>/MD</code> or <code>/MDd</code> switch). Also, the <code>mimalloc-redirect.dll</code> (or <code>mimalloc-redirect32.dll</code>) must be available in the same folder as the main <code>mimalloc-override.dll</code> at runtime (as it is a dependency). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc (in <code>mimalloc-override.dll</code>).</p>
+<p>To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some call to the mimalloc API in the <code>main</code> function, like <code>mi_version()</code> (or use the <code>/INCLUDE:mi_version</code> switch on the linker). See the <code>mimalloc-override-test</code> project for an example on how to use this. For best performance on Windows with C++, it is also recommended to also override the <code>new</code>/<code>delete</code> operations (by including <a href="https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h"><code>mimalloc-new-delete.h</code></a> a single(!) source file in your project without linking to the mimalloc library).</p>
+<p>The environment variable <code>MIMALLOC_DISABLE_REDIRECT=1</code> can be used to disable dynamic overriding at run-time. Use <code>MIMALLOC_VERBOSE=1</code> to check if mimalloc was successfully redirected.</p>
+<p>(Note: in principle, it is possible to even patch existing executables without any recompilation if they are linked with the dynamic C runtime (<code>ucrtbase.dll</code>) &ndash; just put the <code>mimalloc-override.dll</code> into the import table (and put <code>mimalloc-redirect.dll</code> in the same folder) Such patching can be done for example with <a href="https://ntcore.com/?page_id=388">CFF Explorer</a>).</p>
+<h2>Static override</h2>
+<p>On Unix systems, you can also statically link with <em>mimalloc</em> to override the standard malloc interface. The recommended way is to link the final program with the <em>mimalloc</em> single object file (<code>mimalloc-override.o</code>). We use an object file instead of a library file as linkers give preference to that over archives to resolve symbols. To ensure that the standard malloc interface resolves to the <em>mimalloc</em> library, link it as the first object file. For example:</p>
+<div class="fragment"><div class="line">gcc -o myprogram mimalloc-<span class="keyword">override</span>.o  myfile1.c ...</div>
+</div><!-- fragment --><h2>List of Overrides:</h2>
+<p>The specific functions that get redirected to the <em>mimalloc</em> library are:</p>
+<div class="fragment"><div class="line"><span class="comment">// C</span></div>
+<div class="line"><span class="keywordtype">void</span>*  malloc(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><span class="keywordtype">void</span>*  calloc(<span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> n);</div>
+<div class="line"><span class="keywordtype">void</span>*  realloc(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><span class="keywordtype">void</span>   free(<span class="keywordtype">void</span>* p);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span>*  aligned_alloc(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><span class="keywordtype">char</span>*  strdup(<span class="keyword">const</span> <span class="keywordtype">char</span>* s);</div>
+<div class="line"><span class="keywordtype">char</span>*  strndup(<span class="keyword">const</span> <span class="keywordtype">char</span>* s, <span class="keywordtype">size_t</span> n);</div>
+<div class="line"><span class="keywordtype">char</span>*  realpath(<span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">char</span>* resolved_name);</div>
+<div class="line"> </div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// C++</span></div>
+<div class="line"><span class="keywordtype">void</span>   <span class="keyword">operator</span> <span class="keyword">delete</span>(<span class="keywordtype">void</span>* p);</div>
+<div class="line"><span class="keywordtype">void</span>   <span class="keyword">operator</span> <span class="keyword">delete</span>[](<span class="keywordtype">void</span>* p);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>(std::size_t n) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>[](std::size_t n) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>( std::size_t n, std::align_val_t align) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>[]( std::size_t n, std::align_val_t align) noexcept(<span class="keyword">false</span>);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>  ( std::size_t count, <span class="keyword">const</span> std::nothrow_t&amp; tag);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>[]( std::size_t count, <span class="keyword">const</span> std::nothrow_t&amp; tag);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>  ( std::size_t count, std::align_val_t al, <span class="keyword">const</span> std::nothrow_t&amp;);</div>
+<div class="line"><span class="keywordtype">void</span>*  <span class="keyword">operator</span> <span class="keyword">new</span>[]( std::size_t count, std::align_val_t al, <span class="keyword">const</span> std::nothrow_t&amp;);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Posix</span></div>
+<div class="line"><span class="keywordtype">int</span>    posix_memalign(<span class="keywordtype">void</span>** p, <span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Linux</span></div>
+<div class="line"><span class="keywordtype">void</span>*  memalign(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"><span class="keywordtype">void</span>*  valloc(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><span class="keywordtype">void</span>*  pvalloc(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"><span class="keywordtype">size_t</span> malloc_usable_size(<span class="keywordtype">void</span> *p);</div>
+<div class="line"><span class="keywordtype">void</span>*  reallocf(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// macOS</span></div>
+<div class="line"><span class="keywordtype">void</span>   vfree(<span class="keywordtype">void</span>* p);</div>
+<div class="line"><span class="keywordtype">size_t</span> malloc_size(<span class="keyword">const</span> <span class="keywordtype">void</span>* p);</div>
+<div class="line"><span class="keywordtype">size_t</span> malloc_good_size(<span class="keywordtype">size_t</span> size);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// BSD</span></div>
+<div class="line"><span class="keywordtype">void</span>*  reallocarray( <span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size );</div>
+<div class="line"><span class="keywordtype">void</span>*  reallocf(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><span class="keywordtype">void</span>   cfree(<span class="keywordtype">void</span>* p);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// NetBSD</span></div>
+<div class="line"><span class="keywordtype">int</span>    reallocarr(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Windows</span></div>
+<div class="line"><span class="keywordtype">void</span>*  _expand(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize);</div>
+<div class="line"><span class="keywordtype">size_t</span> _msize(<span class="keywordtype">void</span>* p);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span>*  _malloc_dbg(<span class="keywordtype">size_t</span> size, <span class="keywordtype">int</span> block_type, <span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">int</span> line);</div>
+<div class="line"><span class="keywordtype">void</span>*  _realloc_dbg(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> newsize, <span class="keywordtype">int</span> block_type, <span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">int</span> line);</div>
+<div class="line"><span class="keywordtype">void</span>*  _calloc_dbg(<span class="keywordtype">size_t</span> count, <span class="keywordtype">size_t</span> size, <span class="keywordtype">int</span> block_type, <span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">int</span> line);</div>
+<div class="line"><span class="keywordtype">void</span>*  _expand_dbg(<span class="keywordtype">void</span>* p, <span class="keywordtype">size_t</span> size, <span class="keywordtype">int</span> block_type, <span class="keyword">const</span> <span class="keywordtype">char</span>* fname, <span class="keywordtype">int</span> line);</div>
+<div class="line"><span class="keywordtype">size_t</span> _msize_dbg(<span class="keywordtype">void</span>* p, <span class="keywordtype">int</span> block_type);</div>
+<div class="line"><span class="keywordtype">void</span>   _free_dbg(<span class="keywordtype">void</span>* p, <span class="keywordtype">int</span> block_type);</div>
+</div><!-- fragment --> </div></div><!-- contents -->
+</div><!-- PageDoc -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/pages.html b/extlib/mimalloc/docs/pages.html
new file mode 100644 (file)
index 0000000..6999a81
--- /dev/null
@@ -0,0 +1,119 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Related Pages</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('pages.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Related Pages</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="build.html" target="_self">Building</a></td><td class="desc"></td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="using.html" target="_self">Using the library</a></td><td class="desc"></td></tr>
+<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="environment.html" target="_self">Environment Options</a></td><td class="desc"></td></tr>
+<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="overrides.html" target="_self">Overriding Malloc</a></td><td class="desc"></td></tr>
+<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="bench.html" target="_self">Performance</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/resize.js b/extlib/mimalloc/docs/resize.js
new file mode 100644 (file)
index 0000000..e1ad0fe
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ @licstart  The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend  The above is the entire license notice for the JavaScript code in this file
+ */
+function initResizable()
+{
+  var cookie_namespace = 'doxygen';
+  var sidenav,navtree,content,header,collapsed,collapsedWidth=0,barWidth=6,desktop_vp=768,titleHeight;
+
+  function readCookie(cookie)
+  {
+    var myCookie = cookie_namespace+"_"+cookie+"=";
+    if (document.cookie) {
+      var index = document.cookie.indexOf(myCookie);
+      if (index != -1) {
+        var valStart = index + myCookie.length;
+        var valEnd = document.cookie.indexOf(";", valStart);
+        if (valEnd == -1) {
+          valEnd = document.cookie.length;
+        }
+        var val = document.cookie.substring(valStart, valEnd);
+        return val;
+      }
+    }
+    return 0;
+  }
+
+  function writeCookie(cookie, val, expiration)
+  {
+    if (val==undefined) return;
+    if (expiration == null) {
+      var date = new Date();
+      date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
+      expiration = date.toGMTString();
+    }
+    document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/";
+  }
+
+  function resizeWidth()
+  {
+    var windowWidth = $(window).width() + "px";
+    var sidenavWidth = $(sidenav).outerWidth();
+    content.css({marginLeft:parseInt(sidenavWidth)+"px"});
+    writeCookie('width',sidenavWidth-barWidth, null);
+  }
+
+  function restoreWidth(navWidth)
+  {
+    var windowWidth = $(window).width() + "px";
+    content.css({marginLeft:parseInt(navWidth)+barWidth+"px"});
+    sidenav.css({width:navWidth + "px"});
+  }
+
+  function resizeHeight()
+  {
+    var headerHeight = header.outerHeight();
+    var footerHeight = footer.outerHeight();
+    var windowHeight = $(window).height() - headerHeight - footerHeight;
+    content.css({height:windowHeight + "px"});
+    navtree.css({height:windowHeight + "px"});
+    sidenav.css({height:windowHeight + "px"});
+    var width=$(window).width();
+    if (width!=collapsedWidth) {
+      if (width<desktop_vp && collapsedWidth>=desktop_vp) {
+        if (!collapsed) {
+          collapseExpand();
+        }
+      } else if (width>desktop_vp && collapsedWidth<desktop_vp) {
+        if (collapsed) {
+          collapseExpand();
+        }
+      }
+      collapsedWidth=width;
+    }
+    if (location.hash.slice(1)) {
+      (document.getElementById(location.hash.slice(1))||document.body).scrollIntoView();
+    }
+  }
+
+  function collapseExpand()
+  {
+    if (sidenav.width()>0) {
+      restoreWidth(0);
+      collapsed=true;
+    }
+    else {
+      var width = readCookie('width');
+      if (width>200 && width<$(window).width()) { restoreWidth(width); } else { restoreWidth(200); }
+      collapsed=false;
+    }
+  }
+
+  header  = $("#top");
+  sidenav = $("#side-nav");
+  content = $("#doc-content");
+  navtree = $("#nav-tree");
+  footer  = $("#nav-path");
+  $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } });
+  $(sidenav).resizable({ minWidth: 0 });
+  $(window).resize(function() { resizeHeight(); });
+  var device = navigator.userAgent.toLowerCase();
+  var touch_device = device.match(/(iphone|ipod|ipad|android)/);
+  if (touch_device) { /* wider split bar for touch only devices */
+    $(sidenav).css({ paddingRight:'20px' });
+    $('.ui-resizable-e').css({ width:'20px' });
+    $('#nav-sync').css({ right:'34px' });
+    barWidth=20;
+  }
+  var width = readCookie('width');
+  if (width) { restoreWidth(width); } else { resizeWidth(); }
+  resizeHeight();
+  var url = location.href;
+  var i=url.indexOf("#");
+  if (i>=0) window.location.hash=url.substr(i);
+  var _preventDefault = function(evt) { evt.preventDefault(); };
+  $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault);
+  $(".ui-resizable-handle").dblclick(collapseExpand);
+  $(window).on('load',resizeHeight);
+}
+/* @license-end */
diff --git a/extlib/mimalloc/docs/search/all_0.html b/extlib/mimalloc/docs/search/all_0.html
new file mode 100644 (file)
index 0000000..1ec5b2d
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_0.js b/extlib/mimalloc/docs/search/all_0.js
new file mode 100644 (file)
index 0000000..cd7bb41
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['_5fmi_5foption_5flast_0',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_1.html b/extlib/mimalloc/docs/search/all_1.html
new file mode 100644 (file)
index 0000000..9f80e90
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_1.js b/extlib/mimalloc/docs/search/all_1.js
new file mode 100644 (file)
index 0000000..7f1097c
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['aligned_20allocation_1',['Aligned Allocation',['../group__aligned.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_2.html b/extlib/mimalloc/docs/search/all_2.html
new file mode 100644 (file)
index 0000000..02cfffc
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_2.js b/extlib/mimalloc/docs/search/all_2.js
new file mode 100644 (file)
index 0000000..00576d7
--- /dev/null
@@ -0,0 +1,7 @@
+var searchData=
+[
+  ['basic_20allocation_2',['Basic Allocation',['../group__malloc.html',1,'']]],
+  ['block_5fsize_3',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
+  ['blocks_4',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]],
+  ['building_5',['Building',['../build.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_3.html b/extlib/mimalloc/docs/search/all_3.html
new file mode 100644 (file)
index 0000000..39767b8
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_3.js b/extlib/mimalloc/docs/search/all_3.js
new file mode 100644 (file)
index 0000000..9a029ee
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['c_2b_2b_20wrappers_6',['C++ wrappers',['../group__cpp.html',1,'']]],
+  ['committed_7',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_4.html b/extlib/mimalloc/docs/search/all_4.html
new file mode 100644 (file)
index 0000000..fc40463
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_4.js b/extlib/mimalloc/docs/search/all_4.js
new file mode 100644 (file)
index 0000000..5dc5128
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['environment_20options_8',['Environment Options',['../environment.html',1,'']]],
+  ['extended_20functions_9',['Extended Functions',['../group__extended.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_5.html b/extlib/mimalloc/docs/search/all_5.html
new file mode 100644 (file)
index 0000000..9dd9344
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_5.js b/extlib/mimalloc/docs/search/all_5.js
new file mode 100644 (file)
index 0000000..7441d85
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['heap_20allocation_10',['Heap Allocation',['../group__heap.html',1,'']]],
+  ['heap_20introspection_11',['Heap Introspection',['../group__analysis.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_6.html b/extlib/mimalloc/docs/search/all_6.html
new file mode 100644 (file)
index 0000000..f1e516d
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_6.js b/extlib/mimalloc/docs/search/all_6.js
new file mode 100644 (file)
index 0000000..6d32b7b
--- /dev/null
@@ -0,0 +1,153 @@
+var searchData=
+[
+  ['mi_5f_5fposix_5fmemalign_12',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
+  ['mi_5faligned_5falloc_13',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
+  ['mi_5falignment_5fmax_14',['MI_ALIGNMENT_MAX',['../group__aligned.html#ga83c03016066b438f51a8095e9140be06',1,'mimalloc-doc.h']]],
+  ['mi_5fblock_5fvisit_5ffun_15',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_16',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_5faligned_17',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_5faligned_5fat_18',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_5ftp_19',['mi_calloc_tp',['../group__typed.html#gae80c47c9d4cab10961fff1a8ac98fc07',1,'mimalloc-doc.h']]],
+  ['mi_5fcfree_20',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
+  ['mi_5fcheck_5fowned_21',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
+  ['mi_5fcollect_22',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
+  ['mi_5fdeferred_5ffree_5ffun_23',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
+  ['mi_5ferror_5ffun_24',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
+  ['mi_5fexpand_25',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_26',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5faligned_27',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5fsize_28',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5fsize_5faligned_29',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
+  ['mi_5fgood_5fsize_30',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5farea_5ft_31',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
+  ['mi_5fheap_5fcalloc_32',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_5faligned_33',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_5faligned_5fat_34',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_5ftp_35',['mi_heap_calloc_tp',['../group__typed.html#ga4e5d1f1707c90e5f55e023ac5f45fe74',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcheck_5fowned_36',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcollect_37',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcontains_5fblock_38',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fdelete_39',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fdestroy_40',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fget_5fbacking_41',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fget_5fdefault_42',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_43',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5faligned_44',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5faligned_5fat_45',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5fsmall_46',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5ftp_47',['mi_heap_malloc_tp',['../group__typed.html#ga653bcb24ac495bc19940ecd6898f9cd7',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmallocn_48',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmallocn_5ftp_49',['mi_heap_mallocn_tp',['../group__typed.html#ga6b75cb9c4b9c647661d0924552dc6e83',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fnew_50',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_51',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_5faligned_52',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_5faligned_5fat_53',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5freallocf_54',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5freallocn_55',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5freallocn_5ftp_56',['mi_heap_reallocn_tp',['../group__typed.html#gaf213d5422ec35e7f6caad827c79bc948',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealpath_57',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_58',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_5faligned_59',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_5faligned_5fat_60',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_5ftp_61',['mi_heap_recalloc_tp',['../group__typed.html#ga3e50a1600958fcaf1a7f3560c9174f9e',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_62',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_5faligned_63',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_5faligned_5fat_64',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fset_5fdefault_65',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fstrdup_66',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fstrndup_67',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5ft_68',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fvisit_5fblocks_69',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_70',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_5faligned_71',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_5faligned_5fat_72',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_5ftp_73',['mi_heap_zalloc_tp',['../group__typed.html#gad6e87e86e994aa14416ae9b5d4c188fe',1,'mimalloc-doc.h']]],
+  ['mi_5fis_5fin_5fheap_5fregion_74',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
+  ['mi_5fis_5fredirected_75',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_76',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5faligned_77',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5faligned_5fat_78',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fsize_79',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fsmall_80',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5ftp_81',['mi_malloc_tp',['../group__typed.html#ga0619a62c5fd886f1016030abe91f0557',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fusable_5fsize_82',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
+  ['mi_5fmallocn_83',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
+  ['mi_5fmallocn_5ftp_84',['mi_mallocn_tp',['../group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b',1,'mimalloc-doc.h']]],
+  ['mi_5fmanage_5fos_5fmemory_85',['mi_manage_os_memory',['../group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf',1,'mimalloc-doc.h']]],
+  ['mi_5fmemalign_86',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_87',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5faligned_88',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5faligned_5fnothrow_89',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5fn_90',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5fnothrow_91',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5frealloc_92',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5freallocn_93',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fdisable_94',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5feager_5fcommit_95',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5feager_5fcommit_5fdelay_96',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5feager_5fregion_5fcommit_97',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fenable_98',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fget_99',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fis_5fenabled_100',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5flarge_5fos_5fpages_101',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fos_5ftag_102',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fpage_5freset_103',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freserve_5fhuge_5fos_5fpages_104',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freserve_5fhuge_5fos_5fpages_5fat_105',['mi_option_reserve_huge_os_pages_at',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freset_5fdecommits_106',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freset_5fdelay_107',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fsegment_5fcache_108',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fsegment_5freset_109',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_110',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fdefault_111',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fenabled_112',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fenabled_5fdefault_113',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fshow_5ferrors_114',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fshow_5fstats_115',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5ft_116',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fuse_5fnuma_5fnodes_117',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fverbose_118',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]],
+  ['mi_5foutput_5ffun_119',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]],
+  ['mi_5fposix_5fmemalign_120',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
+  ['mi_5fprocess_5finfo_121',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
+  ['mi_5fpvalloc_122',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_123',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_5faligned_124',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_5faligned_5fat_125',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
+  ['mi_5freallocarr_126',['mi_reallocarr',['../group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5',1,'mimalloc-doc.h']]],
+  ['mi_5freallocarray_127',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
+  ['mi_5freallocf_128',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
+  ['mi_5freallocn_129',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
+  ['mi_5freallocn_5ftp_130',['mi_reallocn_tp',['../group__typed.html#ga1158b49a55dfa81f58a4426a7578f523',1,'mimalloc-doc.h']]],
+  ['mi_5frealpath_131',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_132',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_5faligned_133',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_5faligned_5fat_134',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5fdeferred_5ffree_135',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5ferror_136',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5foutput_137',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fhuge_5fos_5fpages_5fat_138',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave_139',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fos_5fmemory_140',['mi_reserve_os_memory',['../group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_141',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_5faligned_142',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_5faligned_5fat_143',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
+  ['mi_5fsmall_5fsize_5fmax_144',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fmerge_145',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fprint_146',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fprint_5fout_147',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5freset_148',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
+  ['mi_5fstl_5fallocator_149',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]],
+  ['mi_5fstrdup_150',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
+  ['mi_5fstrndup_151',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5fdone_152',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5finit_153',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5fstats_5fprint_5fout_154',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
+  ['mi_5fusable_5fsize_155',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
+  ['mi_5fvalloc_156',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_157',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5faligned_158',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5faligned_5fat_159',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5fsmall_160',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5ftp_161',['mi_zalloc_tp',['../group__typed.html#gac77a61bdaf680a803785fe307820b48c',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_7.html b/extlib/mimalloc/docs/search/all_7.html
new file mode 100644 (file)
index 0000000..8ddbf6c
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_7.js b/extlib/mimalloc/docs/search/all_7.js
new file mode 100644 (file)
index 0000000..8f296aa
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['overriding_20malloc_162',['Overriding Malloc',['../overrides.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_8.html b/extlib/mimalloc/docs/search/all_8.html
new file mode 100644 (file)
index 0000000..83c55ae
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_8.js b/extlib/mimalloc/docs/search/all_8.js
new file mode 100644 (file)
index 0000000..a9caa77
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['performance_163',['Performance',['../bench.html',1,'']]],
+  ['posix_164',['Posix',['../group__posix.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_9.html b/extlib/mimalloc/docs/search/all_9.html
new file mode 100644 (file)
index 0000000..1e263c1
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_9.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_9.js b/extlib/mimalloc/docs/search/all_9.js
new file mode 100644 (file)
index 0000000..f6b4ba3
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['reserved_165',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]],
+  ['runtime_20options_166',['Runtime Options',['../group__options.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_a.html b/extlib/mimalloc/docs/search/all_a.html
new file mode 100644 (file)
index 0000000..3a6cac1
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_a.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_a.js b/extlib/mimalloc/docs/search/all_a.js
new file mode 100644 (file)
index 0000000..699b545
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['typed_20macros_167',['Typed Macros',['../group__typed.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_b.html b/extlib/mimalloc/docs/search/all_b.html
new file mode 100644 (file)
index 0000000..130deb4
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_b.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_b.js b/extlib/mimalloc/docs/search/all_b.js
new file mode 100644 (file)
index 0000000..73a2671
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['used_168',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]],
+  ['using_20the_20library_169',['Using the library',['../using.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_c.html b/extlib/mimalloc/docs/search/all_c.html
new file mode 100644 (file)
index 0000000..3dd5af0
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_c.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_c.js b/extlib/mimalloc/docs/search/all_c.js
new file mode 100644 (file)
index 0000000..192fb1c
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['zero_20initialized_20re_2dallocation_170',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/all_d.html b/extlib/mimalloc/docs/search/all_d.html
new file mode 100644 (file)
index 0000000..a2d5bd7
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.15"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_d.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/all_d.js b/extlib/mimalloc/docs/search/all_d.js
new file mode 100644 (file)
index 0000000..2b9b4ce
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/classes_0.html b/extlib/mimalloc/docs/search/classes_0.html
new file mode 100644 (file)
index 0000000..af8159e
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="classes_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/classes_0.js b/extlib/mimalloc/docs/search/classes_0.js
new file mode 100644 (file)
index 0000000..e3770fb
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['mi_5fheap_5farea_5ft_171',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
+  ['mi_5fstl_5fallocator_172',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/close.png b/extlib/mimalloc/docs/search/close.png
new file mode 100644 (file)
index 0000000..9342d3d
Binary files /dev/null and b/extlib/mimalloc/docs/search/close.png differ
diff --git a/extlib/mimalloc/docs/search/enums_0.html b/extlib/mimalloc/docs/search/enums_0.html
new file mode 100644 (file)
index 0000000..141fff5
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enums_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/enums_0.js b/extlib/mimalloc/docs/search/enums_0.js
new file mode 100644 (file)
index 0000000..6f1f383
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['mi_5foption_5ft_296',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/enumvalues_0.html b/extlib/mimalloc/docs/search/enumvalues_0.html
new file mode 100644 (file)
index 0000000..0d131d9
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enumvalues_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/enumvalues_0.js b/extlib/mimalloc/docs/search/enumvalues_0.js
new file mode 100644 (file)
index 0000000..1aca63b
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['_5fmi_5foption_5flast_297',['_mi_option_last',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/enumvalues_1.html b/extlib/mimalloc/docs/search/enumvalues_1.html
new file mode 100644 (file)
index 0000000..cd9187a
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enumvalues_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/enumvalues_1.js b/extlib/mimalloc/docs/search/enumvalues_1.js
new file mode 100644 (file)
index 0000000..bd525bb
--- /dev/null
@@ -0,0 +1,19 @@
+var searchData=
+[
+  ['mi_5foption_5feager_5fcommit_298',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5feager_5fcommit_5fdelay_299',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5feager_5fregion_5fcommit_300',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5flarge_5fos_5fpages_301',['mi_option_large_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fos_5ftag_302',['mi_option_os_tag',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fpage_5freset_303',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freserve_5fhuge_5fos_5fpages_304',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freserve_5fhuge_5fos_5fpages_5fat_305',['mi_option_reserve_huge_os_pages_at',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caa13e7926d4339d2aa6fbf61d4473fd5c',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freset_5fdecommits_306',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5freset_5fdelay_307',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fsegment_5fcache_308',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fsegment_5freset_309',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fshow_5ferrors_310',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fshow_5fstats_311',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fuse_5fnuma_5fnodes_312',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fverbose_313',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/functions_0.html b/extlib/mimalloc/docs/search/functions_0.html
new file mode 100644 (file)
index 0000000..eb4c501
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="functions_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/functions_0.js b/extlib/mimalloc/docs/search/functions_0.js
new file mode 100644 (file)
index 0000000..b44917a
--- /dev/null
@@ -0,0 +1,116 @@
+var searchData=
+[
+  ['mi_5f_5fposix_5fmemalign_173',['mi__posix_memalign',['../group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a',1,'mimalloc-doc.h']]],
+  ['mi_5faligned_5falloc_174',['mi_aligned_alloc',['../group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_175',['mi_calloc',['../group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_5faligned_176',['mi_calloc_aligned',['../group__aligned.html#ga53dddb4724042a90315b94bc268fb4c9',1,'mimalloc-doc.h']]],
+  ['mi_5fcalloc_5faligned_5fat_177',['mi_calloc_aligned_at',['../group__aligned.html#ga08647c4593f3b2eef24a919a73eba3a3',1,'mimalloc-doc.h']]],
+  ['mi_5fcfree_178',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
+  ['mi_5fcheck_5fowned_179',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
+  ['mi_5fcollect_180',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
+  ['mi_5fexpand_181',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_182',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5faligned_183',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5fsize_184',['mi_free_size',['../group__posix.html#gae01389eedab8d67341ff52e2aad80ebb',1,'mimalloc-doc.h']]],
+  ['mi_5ffree_5fsize_5faligned_185',['mi_free_size_aligned',['../group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc',1,'mimalloc-doc.h']]],
+  ['mi_5fgood_5fsize_186',['mi_good_size',['../group__extended.html#gac057927cd06c854b45fe7847e921bd47',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_187',['mi_heap_calloc',['../group__heap.html#gaa6702b3c48e9e53e50e81b36f5011d55',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_5faligned_188',['mi_heap_calloc_aligned',['../group__heap.html#ga4af03a6e2b93fae77424d93f889705c3',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcalloc_5faligned_5fat_189',['mi_heap_calloc_aligned_at',['../group__heap.html#ga08ca6419a5c057a4d965868998eef487',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcheck_5fowned_190',['mi_heap_check_owned',['../group__analysis.html#ga0d67c1789faaa15ff366c024fcaf6377',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcollect_191',['mi_heap_collect',['../group__heap.html#ga7922f7495cde30b1984d0e6072419298',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fcontains_5fblock_192',['mi_heap_contains_block',['../group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fdelete_193',['mi_heap_delete',['../group__heap.html#ga2ab1af8d438819b55319c7ef51d1e409',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fdestroy_194',['mi_heap_destroy',['../group__heap.html#ga9f9c0844edb9717f4feacd79116b8e0d',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fget_5fbacking_195',['mi_heap_get_backing',['../group__heap.html#ga5d03fbe062ffcf38f0f417fd968357fc',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fget_5fdefault_196',['mi_heap_get_default',['../group__heap.html#ga8db4cbb87314a989a9a187464d6b5e05',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_197',['mi_heap_malloc',['../group__heap.html#ga9cbed01e42c0647907295de92c3fa296',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5faligned_198',['mi_heap_malloc_aligned',['../group__heap.html#gab5b87e1805306f70df38789fcfcf6653',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5faligned_5fat_199',['mi_heap_malloc_aligned_at',['../group__heap.html#ga23acd7680fb0976dde3783254c6c874b',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmalloc_5fsmall_200',['mi_heap_malloc_small',['../group__heap.html#gaa1a1c7a1f4da6826b5a25b70ef878368',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fmallocn_201',['mi_heap_mallocn',['../group__heap.html#ga851da6c43fe0b71c1376cee8aef90db0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fnew_202',['mi_heap_new',['../group__heap.html#ga766f672ba56f2fbfeb9d9dbb0b7f6b11',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_203',['mi_heap_realloc',['../group__heap.html#gaaef3395f66be48f37bdc8322509c5d81',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_5faligned_204',['mi_heap_realloc_aligned',['../group__heap.html#gafc603b696bd14cae6da28658f950d98c',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealloc_5faligned_5fat_205',['mi_heap_realloc_aligned_at',['../group__heap.html#gaf96c788a1bf553fe2d371de9365e047c',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5freallocf_206',['mi_heap_reallocf',['../group__heap.html#ga4a21070eb4e7cce018133c8d5f4b0527',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5freallocn_207',['mi_heap_reallocn',['../group__heap.html#gac74e94ad9b0c9b57c1c4d88b8825b7a8',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frealpath_208',['mi_heap_realpath',['../group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_209',['mi_heap_recalloc',['../group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_5faligned_210',['mi_heap_recalloc_aligned',['../group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frecalloc_5faligned_5fat_211',['mi_heap_recalloc_aligned_at',['../group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_212',['mi_heap_rezalloc',['../group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_5faligned_213',['mi_heap_rezalloc_aligned',['../group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5frezalloc_5faligned_5fat_214',['mi_heap_rezalloc_aligned_at',['../group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fset_5fdefault_215',['mi_heap_set_default',['../group__heap.html#gab8631ec88c8d26641b68b5d25dcd4422',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fstrdup_216',['mi_heap_strdup',['../group__heap.html#ga139d6b09dbf50c3c2523d0f4d1cfdeb5',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fstrndup_217',['mi_heap_strndup',['../group__heap.html#ga8e3dbd46650dd26573cf307a2c8f1f5a',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fvisit_5fblocks_218',['mi_heap_visit_blocks',['../group__analysis.html#ga70c46687dc6e9dc98b232b02646f8bed',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_219',['mi_heap_zalloc',['../group__heap.html#ga903104592c8ed53417a3762da6241133',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_5faligned_220',['mi_heap_zalloc_aligned',['../group__heap.html#gaa450a59c6c7ae5fdbd1c2b80a8329ef0',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5fzalloc_5faligned_5fat_221',['mi_heap_zalloc_aligned_at',['../group__heap.html#ga45fb43a62776fbebbdf1edd99b527954',1,'mimalloc-doc.h']]],
+  ['mi_5fis_5fin_5fheap_5fregion_222',['mi_is_in_heap_region',['../group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6',1,'mimalloc-doc.h']]],
+  ['mi_5fis_5fredirected_223',['mi_is_redirected',['../group__extended.html#gaad25050b19f30cd79397b227e0157a3f',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_224',['mi_malloc',['../group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5faligned_225',['mi_malloc_aligned',['../group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5faligned_5fat_226',['mi_malloc_aligned_at',['../group__aligned.html#ga5850da130c936bd77db039dcfbc8295d',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fsize_227',['mi_malloc_size',['../group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fsmall_228',['mi_malloc_small',['../group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99',1,'mimalloc-doc.h']]],
+  ['mi_5fmalloc_5fusable_5fsize_229',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
+  ['mi_5fmallocn_230',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
+  ['mi_5fmanage_5fos_5fmemory_231',['mi_manage_os_memory',['../group__extended.html#ga4c6486a1fdcd7a423b5f25fe4be8e0cf',1,'mimalloc-doc.h']]],
+  ['mi_5fmemalign_232',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_233',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5faligned_234',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5faligned_5fnothrow_235',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5fn_236',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5fnothrow_237',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5frealloc_238',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
+  ['mi_5fnew_5freallocn_239',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fdisable_240',['mi_option_disable',['../group__options.html#gaebf6ff707a2e688ebb1a2296ca564054',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fenable_241',['mi_option_enable',['../group__options.html#ga04180ae41b0d601421dd62ced40ca050',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fget_242',['mi_option_get',['../group__options.html#ga7e8af195cc81d3fa64ccf2662caa565a',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fis_5fenabled_243',['mi_option_is_enabled',['../group__options.html#ga459ad98f18b3fc9275474807fe0ca188',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_244',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fdefault_245',['mi_option_set_default',['../group__options.html#ga7ef623e440e6e5545cb08c94e71e4b90',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fenabled_246',['mi_option_set_enabled',['../group__options.html#ga9a13d05fcb77489cb06d4d017ebd8bed',1,'mimalloc-doc.h']]],
+  ['mi_5foption_5fset_5fenabled_5fdefault_247',['mi_option_set_enabled_default',['../group__options.html#ga65518b69ec5d32336b50e07f74b3f629',1,'mimalloc-doc.h']]],
+  ['mi_5fposix_5fmemalign_248',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
+  ['mi_5fprocess_5finfo_249',['mi_process_info',['../group__extended.html#ga7d862c2affd5790381da14eb102a364d',1,'mimalloc-doc.h']]],
+  ['mi_5fpvalloc_250',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_251',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_5faligned_252',['mi_realloc_aligned',['../group__aligned.html#ga4028d1cf4aa4c87c880747044a8322ae',1,'mimalloc-doc.h']]],
+  ['mi_5frealloc_5faligned_5fat_253',['mi_realloc_aligned_at',['../group__aligned.html#gaf66a9ae6c6f08bd6be6fb6ea771faffb',1,'mimalloc-doc.h']]],
+  ['mi_5freallocarr_254',['mi_reallocarr',['../group__posix.html#ga7e1934d60a3e697950eeb48e042bfad5',1,'mimalloc-doc.h']]],
+  ['mi_5freallocarray_255',['mi_reallocarray',['../group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088',1,'mimalloc-doc.h']]],
+  ['mi_5freallocf_256',['mi_reallocf',['../group__malloc.html#gafe68ac7c5e24a65cd55c9d6b152211a0',1,'mimalloc-doc.h']]],
+  ['mi_5freallocn_257',['mi_reallocn',['../group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853',1,'mimalloc-doc.h']]],
+  ['mi_5frealpath_258',['mi_realpath',['../group__malloc.html#ga08cec32dd5bbe7da91c78d19f1b5bebe',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_259',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_5faligned_260',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
+  ['mi_5frecalloc_5faligned_5fat_261',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5fdeferred_5ffree_262',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5ferror_263',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
+  ['mi_5fregister_5foutput_264',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fhuge_5fos_5fpages_5fat_265',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fhuge_5fos_5fpages_5finterleave_266',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
+  ['mi_5freserve_5fos_5fmemory_267',['mi_reserve_os_memory',['../group__extended.html#ga00ec3324b6b2591c7fe3677baa30a767',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_268',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_5faligned_269',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
+  ['mi_5frezalloc_5faligned_5fat_270',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fmerge_271',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fprint_272',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5fprint_5fout_273',['mi_stats_print_out',['../group__extended.html#ga537f13b299ddf801e49a5a94fde02c79',1,'mimalloc-doc.h']]],
+  ['mi_5fstats_5freset_274',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
+  ['mi_5fstrdup_275',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
+  ['mi_5fstrndup_276',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5fdone_277',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5finit_278',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
+  ['mi_5fthread_5fstats_5fprint_5fout_279',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
+  ['mi_5fusable_5fsize_280',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
+  ['mi_5fvalloc_281',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_282',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5faligned_283',['mi_zalloc_aligned',['../group__aligned.html#ga0cadbcf5b89a7b6fb171bc8df8734819',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5faligned_5fat_284',['mi_zalloc_aligned_at',['../group__aligned.html#ga5f8c2353766db522565e642fafd8a3f8',1,'mimalloc-doc.h']]],
+  ['mi_5fzalloc_5fsmall_285',['mi_zalloc_small',['../group__extended.html#ga220f29f40a44404b0061c15bc1c31152',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/functions_1.html b/extlib/mimalloc/docs/search/functions_1.html
new file mode 100644 (file)
index 0000000..bfcf880
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.15"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="functions_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/functions_1.js b/extlib/mimalloc/docs/search/functions_1.js
new file mode 100644 (file)
index 0000000..06dbb19
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['void',['void',['../group__extended.html#gadc49452cc1634aa03ac83ffe9b97a19c',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_0.html b/extlib/mimalloc/docs/search/groups_0.html
new file mode 100644 (file)
index 0000000..c600b49
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_0.js b/extlib/mimalloc/docs/search/groups_0.js
new file mode 100644 (file)
index 0000000..0ed99b8
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['aligned_20allocation_314',['Aligned Allocation',['../group__aligned.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_1.html b/extlib/mimalloc/docs/search/groups_1.html
new file mode 100644 (file)
index 0000000..2eb3550
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_1.js b/extlib/mimalloc/docs/search/groups_1.js
new file mode 100644 (file)
index 0000000..f27c584
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['basic_20allocation_315',['Basic Allocation',['../group__malloc.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_2.html b/extlib/mimalloc/docs/search/groups_2.html
new file mode 100644 (file)
index 0000000..12f4af7
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_2.js b/extlib/mimalloc/docs/search/groups_2.js
new file mode 100644 (file)
index 0000000..6da64b6
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['c_2b_2b_20wrappers_316',['C++ wrappers',['../group__cpp.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_3.html b/extlib/mimalloc/docs/search/groups_3.html
new file mode 100644 (file)
index 0000000..5e235b5
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_3.js b/extlib/mimalloc/docs/search/groups_3.js
new file mode 100644 (file)
index 0000000..cdfbe64
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['extended_20functions_317',['Extended Functions',['../group__extended.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_4.html b/extlib/mimalloc/docs/search/groups_4.html
new file mode 100644 (file)
index 0000000..99405e1
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_4.js b/extlib/mimalloc/docs/search/groups_4.js
new file mode 100644 (file)
index 0000000..687f1ea
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['heap_20allocation_318',['Heap Allocation',['../group__heap.html',1,'']]],
+  ['heap_20introspection_319',['Heap Introspection',['../group__analysis.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_5.html b/extlib/mimalloc/docs/search/groups_5.html
new file mode 100644 (file)
index 0000000..583f5f5
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_5.js b/extlib/mimalloc/docs/search/groups_5.js
new file mode 100644 (file)
index 0000000..43c8b1f
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['posix_320',['Posix',['../group__posix.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_6.html b/extlib/mimalloc/docs/search/groups_6.html
new file mode 100644 (file)
index 0000000..df6a310
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_6.js b/extlib/mimalloc/docs/search/groups_6.js
new file mode 100644 (file)
index 0000000..3463187
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['runtime_20options_321',['Runtime Options',['../group__options.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_7.html b/extlib/mimalloc/docs/search/groups_7.html
new file mode 100644 (file)
index 0000000..8964e05
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_7.js b/extlib/mimalloc/docs/search/groups_7.js
new file mode 100644 (file)
index 0000000..aa150e9
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['typed_20macros_322',['Typed Macros',['../group__typed.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/groups_8.html b/extlib/mimalloc/docs/search/groups_8.html
new file mode 100644 (file)
index 0000000..7987ca3
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/groups_8.js b/extlib/mimalloc/docs/search/groups_8.js
new file mode 100644 (file)
index 0000000..f9c29fe
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['zero_20initialized_20re_2dallocation_323',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/mag_sel.png b/extlib/mimalloc/docs/search/mag_sel.png
new file mode 100644 (file)
index 0000000..39c0ed5
Binary files /dev/null and b/extlib/mimalloc/docs/search/mag_sel.png differ
diff --git a/extlib/mimalloc/docs/search/nomatches.html b/extlib/mimalloc/docs/search/nomatches.html
new file mode 100644 (file)
index 0000000..2b9360b
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="NoMatches">No Matches</div>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_0.html b/extlib/mimalloc/docs/search/pages_0.html
new file mode 100644 (file)
index 0000000..8517b48
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_0.js b/extlib/mimalloc/docs/search/pages_0.js
new file mode 100644 (file)
index 0000000..07922da
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['building_324',['Building',['../build.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/pages_1.html b/extlib/mimalloc/docs/search/pages_1.html
new file mode 100644 (file)
index 0000000..a0fb679
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_1.js b/extlib/mimalloc/docs/search/pages_1.js
new file mode 100644 (file)
index 0000000..6433dae
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['environment_20options_325',['Environment Options',['../environment.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/pages_2.html b/extlib/mimalloc/docs/search/pages_2.html
new file mode 100644 (file)
index 0000000..084edfd
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_2.js b/extlib/mimalloc/docs/search/pages_2.js
new file mode 100644 (file)
index 0000000..7577377
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['overriding_20malloc_326',['Overriding Malloc',['../overrides.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/pages_3.html b/extlib/mimalloc/docs/search/pages_3.html
new file mode 100644 (file)
index 0000000..c0b45b0
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_3.js b/extlib/mimalloc/docs/search/pages_3.js
new file mode 100644 (file)
index 0000000..d62a3cf
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['performance_327',['Performance',['../bench.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/pages_4.html b/extlib/mimalloc/docs/search/pages_4.html
new file mode 100644 (file)
index 0000000..0f05c2e
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/pages_4.js b/extlib/mimalloc/docs/search/pages_4.js
new file mode 100644 (file)
index 0000000..4e4e64d
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['using_20the_20library_328',['Using the library',['../using.html',1,'']]]
+];
diff --git a/extlib/mimalloc/docs/search/search.css b/extlib/mimalloc/docs/search/search.css
new file mode 100644 (file)
index 0000000..10bd4b5
--- /dev/null
@@ -0,0 +1,273 @@
+/*---------------- Search Box */
+
+#FSearchBox {
+    float: left;
+}
+
+#MSearchBox {
+    white-space : nowrap;
+    float: none;
+    margin-top: 0px;
+    right: 0px;
+    width: 170px;
+    height: 24px;
+    z-index: 102;
+    display: inline;
+    position: absolute;
+}
+
+#MSearchBox .left
+{
+    display:block;
+    position:absolute;
+    left:10px;
+    width:20px;
+    height:19px;
+    background:url('search_l.png') no-repeat;
+    background-position:right;
+}
+
+#MSearchSelect {
+    display:block;
+    position:absolute;
+    width:20px;
+    height:19px;
+}
+
+.left #MSearchSelect {
+    left:4px;
+}
+
+.right #MSearchSelect {
+    right:5px;
+}
+
+#MSearchField {
+    display:block;
+    position:absolute;
+    height:19px;
+    background:url('search_m.png') repeat-x;
+    border:none;
+    width:111px;
+    margin-left:20px;
+    padding-left:4px;
+    color: #909090;
+    outline: none;
+    font: 9pt Arial, Verdana, sans-serif;
+    -webkit-border-radius: 0px;
+}
+
+#FSearchBox #MSearchField {
+    margin-left:15px;
+}
+
+#MSearchBox .right {
+    display:block;
+    position:absolute;
+    right:10px;
+    top:0px;
+    width:20px;
+    height:19px;
+    background:url('search_r.png') no-repeat;
+    background-position:left;
+}
+
+#MSearchClose {
+    display: none;
+    position: absolute;
+    top: 4px;
+    background : none;
+    border: none;
+    margin: 0px 4px 0px 0px;
+    padding: 0px 0px;
+    outline: none;
+}
+
+.left #MSearchClose {
+    left: 6px;
+}
+
+.right #MSearchClose {
+    right: 2px;
+}
+
+.MSearchBoxActive #MSearchField {
+    color: #000000;
+}
+
+/*---------------- Search filter selection */
+
+#MSearchSelectWindow {
+    display: none;
+    position: absolute;
+    left: 0; top: 0;
+    border: 1px solid #4F5657;
+    background-color: #F2F3F3;
+    z-index: 10001;
+    padding-top: 4px;
+    padding-bottom: 4px;
+    -moz-border-radius: 4px;
+    -webkit-border-top-left-radius: 4px;
+    -webkit-border-top-right-radius: 4px;
+    -webkit-border-bottom-left-radius: 4px;
+    -webkit-border-bottom-right-radius: 4px;
+    -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+.SelectItem {
+    font: 8pt Arial, Verdana, sans-serif;
+    padding-left:  2px;
+    padding-right: 12px;
+    border: 0px;
+}
+
+span.SelectionMark {
+    margin-right: 4px;
+    font-family: monospace;
+    outline-style: none;
+    text-decoration: none;
+}
+
+a.SelectItem {
+    display: block;
+    outline-style: none;
+    color: #000000; 
+    text-decoration: none;
+    padding-left:   6px;
+    padding-right: 12px;
+}
+
+a.SelectItem:focus,
+a.SelectItem:active {
+    color: #000000; 
+    outline-style: none;
+    text-decoration: none;
+}
+
+a.SelectItem:hover {
+    color: #FFFFFF;
+    background-color: #0F1010;
+    outline-style: none;
+    text-decoration: none;
+    cursor: pointer;
+    display: block;
+}
+
+/*---------------- Search results window */
+
+iframe#MSearchResults {
+    width: 60ex;
+    height: 15em;
+}
+
+#MSearchResultsWindow {
+    display: none;
+    position: absolute;
+    left: 0; top: 0;
+    border: 1px solid #000;
+    background-color: #DADDDE;
+    z-index:10000;
+}
+
+/* ----------------------------------- */
+
+
+#SRIndex {
+    clear:both; 
+    padding-bottom: 15px;
+}
+
+.SREntry {
+    font-size: 10pt;
+    padding-left: 1ex;
+}
+
+.SRPage .SREntry {
+    font-size: 8pt;
+    padding: 1px 5px;
+}
+
+body.SRPage {
+    margin: 5px 2px;
+}
+
+.SRChildren {
+    padding-left: 3ex; padding-bottom: .5em 
+}
+
+.SRPage .SRChildren {
+    display: none;
+}
+
+.SRSymbol {
+    font-weight: bold; 
+    color: #121414;
+    font-family: Arial, Verdana, sans-serif;
+    text-decoration: none;
+    outline: none;
+}
+
+a.SRScope {
+    display: block;
+    color: #121414; 
+    font-family: Arial, Verdana, sans-serif;
+    text-decoration: none;
+    outline: none;
+}
+
+a.SRSymbol:focus, a.SRSymbol:active,
+a.SRScope:focus, a.SRScope:active {
+    text-decoration: underline;
+}
+
+span.SRScope {
+    padding-left: 4px;
+}
+
+.SRPage .SRStatus {
+    padding: 2px 5px;
+    font-size: 8pt;
+    font-style: italic;
+}
+
+.SRResult {
+    display: none;
+}
+
+DIV.searchresults {
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+/*---------------- External search page results */
+
+.searchresult {
+    background-color: #DFE1E2;
+}
+
+.pages b {
+   color: white;
+   padding: 5px 5px 3px 5px;
+   background-image: url("../tab_a.png");
+   background-repeat: repeat-x;
+   text-shadow: 0 1px 1px #000000;
+}
+
+.pages {
+    line-height: 17px;
+    margin-left: 4px;
+    text-decoration: none;
+}
+
+.hl {
+    font-weight: bold;
+}
+
+#searchresults {
+    margin-bottom: 20px;
+}
+
+.searchpages {
+    margin-top: 10px;
+}
+
diff --git a/extlib/mimalloc/docs/search/search.js b/extlib/mimalloc/docs/search/search.js
new file mode 100644 (file)
index 0000000..fb226f7
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ @licstart  The following is the entire license notice for the JavaScript code in this file.
+
+ The MIT License (MIT)
+
+ Copyright (C) 1997-2020 by Dimitri van Heesch
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ @licend  The above is the entire license notice for the JavaScript code in this file
+ */
+function convertToId(search)
+{
+  var result = '';
+  for (i=0;i<search.length;i++)
+  {
+    var c = search.charAt(i);
+    var cn = c.charCodeAt(0);
+    if (c.match(/[a-z0-9\u0080-\uFFFF]/))
+    {
+      result+=c;
+    }
+    else if (cn<16)
+    {
+      result+="_0"+cn.toString(16);
+    }
+    else
+    {
+      result+="_"+cn.toString(16);
+    }
+  }
+  return result;
+}
+
+function getXPos(item)
+{
+  var x = 0;
+  if (item.offsetWidth)
+  {
+    while (item && item!=document.body)
+    {
+      x   += item.offsetLeft;
+      item = item.offsetParent;
+    }
+  }
+  return x;
+}
+
+function getYPos(item)
+{
+  var y = 0;
+  if (item.offsetWidth)
+  {
+     while (item && item!=document.body)
+     {
+       y   += item.offsetTop;
+       item = item.offsetParent;
+     }
+  }
+  return y;
+}
+
+/* A class handling everything associated with the search panel.
+
+   Parameters:
+   name - The name of the global variable that will be
+          storing this instance.  Is needed to be able to set timeouts.
+   resultPath - path to use for external files
+*/
+function SearchBox(name, resultsPath, inFrame, label, extension)
+{
+  if (!name || !resultsPath) {  alert("Missing parameters to SearchBox."); }
+  if (!extension || extension == "") { extension = ".html"; }
+
+  // ---------- Instance variables
+  this.name                  = name;
+  this.resultsPath           = resultsPath;
+  this.keyTimeout            = 0;
+  this.keyTimeoutLength      = 500;
+  this.closeSelectionTimeout = 300;
+  this.lastSearchValue       = "";
+  this.lastResultsPage       = "";
+  this.hideTimeout           = 0;
+  this.searchIndex           = 0;
+  this.searchActive          = false;
+  this.insideFrame           = inFrame;
+  this.searchLabel           = label;
+  this.extension             = extension;
+
+  // ----------- DOM Elements
+
+  this.DOMSearchField = function()
+  {  return document.getElementById("MSearchField");  }
+
+  this.DOMSearchSelect = function()
+  {  return document.getElementById("MSearchSelect");  }
+
+  this.DOMSearchSelectWindow = function()
+  {  return document.getElementById("MSearchSelectWindow");  }
+
+  this.DOMPopupSearchResults = function()
+  {  return document.getElementById("MSearchResults");  }
+
+  this.DOMPopupSearchResultsWindow = function()
+  {  return document.getElementById("MSearchResultsWindow");  }
+
+  this.DOMSearchClose = function()
+  {  return document.getElementById("MSearchClose"); }
+
+  this.DOMSearchBox = function()
+  {  return document.getElementById("MSearchBox");  }
+
+  // ------------ Event Handlers
+
+  // Called when focus is added or removed from the search field.
+  this.OnSearchFieldFocus = function(isActive)
+  {
+    this.Activate(isActive);
+  }
+
+  this.OnSearchSelectShow = function()
+  {
+    var searchSelectWindow = this.DOMSearchSelectWindow();
+    var searchField        = this.DOMSearchSelect();
+
+    if (this.insideFrame)
+    {
+      var left = getXPos(searchField);
+      var top  = getYPos(searchField);
+      left += searchField.offsetWidth + 6;
+      top += searchField.offsetHeight;
+
+      // show search selection popup
+      searchSelectWindow.style.display='block';
+      left -= searchSelectWindow.offsetWidth;
+      searchSelectWindow.style.left =  left + 'px';
+      searchSelectWindow.style.top  =  top  + 'px';
+    }
+    else
+    {
+      var left = getXPos(searchField);
+      var top  = getYPos(searchField);
+      top += searchField.offsetHeight;
+
+      // show search selection popup
+      searchSelectWindow.style.display='block';
+      searchSelectWindow.style.left =  left + 'px';
+      searchSelectWindow.style.top  =  top  + 'px';
+    }
+
+    // stop selection hide timer
+    if (this.hideTimeout)
+    {
+      clearTimeout(this.hideTimeout);
+      this.hideTimeout=0;
+    }
+    return false; // to avoid "image drag" default event
+  }
+
+  this.OnSearchSelectHide = function()
+  {
+    this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
+                                  this.closeSelectionTimeout);
+  }
+
+  // Called when the content of the search field is changed.
+  this.OnSearchFieldChange = function(evt)
+  {
+    if (this.keyTimeout) // kill running timer
+    {
+      clearTimeout(this.keyTimeout);
+      this.keyTimeout = 0;
+    }
+
+    var e  = (evt) ? evt : window.event; // for IE
+    if (e.keyCode==40 || e.keyCode==13)
+    {
+      if (e.shiftKey==1)
+      {
+        this.OnSearchSelectShow();
+        var win=this.DOMSearchSelectWindow();
+        for (i=0;i<win.childNodes.length;i++)
+        {
+          var child = win.childNodes[i]; // get span within a
+          if (child.className=='SelectItem')
+          {
+            child.focus();
+            return;
+          }
+        }
+        return;
+      }
+      else
+      {
+        window.frames.MSearchResults.postMessage("take_focus", "*");
+      }
+    }
+    else if (e.keyCode==27) // Escape out of the search field
+    {
+      this.DOMSearchField().blur();
+      this.DOMPopupSearchResultsWindow().style.display = 'none';
+      this.DOMSearchClose().style.display = 'none';
+      this.lastSearchValue = '';
+      this.Activate(false);
+      return;
+    }
+
+    // strip whitespaces
+    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+
+    if (searchValue != this.lastSearchValue) // search value has changed
+    {
+      if (searchValue != "") // non-empty search
+      {
+        // set timer for search update
+        this.keyTimeout = setTimeout(this.name + '.Search()',
+                                     this.keyTimeoutLength);
+      }
+      else // empty search field
+      {
+        this.DOMPopupSearchResultsWindow().style.display = 'none';
+        this.DOMSearchClose().style.display = 'none';
+        this.lastSearchValue = '';
+      }
+    }
+  }
+
+  this.SelectItemCount = function(id)
+  {
+    var count=0;
+    var win=this.DOMSearchSelectWindow();
+    for (i=0;i<win.childNodes.length;i++)
+    {
+      var child = win.childNodes[i]; // get span within a
+      if (child.className=='SelectItem')
+      {
+        count++;
+      }
+    }
+    return count;
+  }
+
+  this.SelectItemSet = function(id)
+  {
+    var i,j=0;
+    var win=this.DOMSearchSelectWindow();
+    for (i=0;i<win.childNodes.length;i++)
+    {
+      var child = win.childNodes[i]; // get span within a
+      if (child.className=='SelectItem')
+      {
+        var node = child.firstChild;
+        if (j==id)
+        {
+          node.innerHTML='&#8226;';
+        }
+        else
+        {
+          node.innerHTML='&#160;';
+        }
+        j++;
+      }
+    }
+  }
+
+  // Called when an search filter selection is made.
+  // set item with index id as the active item
+  this.OnSelectItem = function(id)
+  {
+    this.searchIndex = id;
+    this.SelectItemSet(id);
+    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+    if (searchValue!="" && this.searchActive) // something was found -> do a search
+    {
+      this.Search();
+    }
+  }
+
+  this.OnSearchSelectKey = function(evt)
+  {
+    var e = (evt) ? evt : window.event; // for IE
+    if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
+    {
+      this.searchIndex++;
+      this.OnSelectItem(this.searchIndex);
+    }
+    else if (e.keyCode==38 && this.searchIndex>0) // Up
+    {
+      this.searchIndex--;
+      this.OnSelectItem(this.searchIndex);
+    }
+    else if (e.keyCode==13 || e.keyCode==27)
+    {
+      this.OnSelectItem(this.searchIndex);
+      this.CloseSelectionWindow();
+      this.DOMSearchField().focus();
+    }
+    return false;
+  }
+
+  // --------- Actions
+
+  // Closes the results window.
+  this.CloseResultsWindow = function()
+  {
+    this.DOMPopupSearchResultsWindow().style.display = 'none';
+    this.DOMSearchClose().style.display = 'none';
+    this.Activate(false);
+  }
+
+  this.CloseSelectionWindow = function()
+  {
+    this.DOMSearchSelectWindow().style.display = 'none';
+  }
+
+  // Performs a search.
+  this.Search = function()
+  {
+    this.keyTimeout = 0;
+
+    // strip leading whitespace
+    var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
+
+    var code = searchValue.toLowerCase().charCodeAt(0);
+    var idxChar = searchValue.substr(0, 1).toLowerCase();
+    if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
+    {
+      idxChar = searchValue.substr(0, 2);
+    }
+
+    var resultsPage;
+    var resultsPageWithSearch;
+    var hasResultsPage;
+
+    var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
+    if (idx!=-1)
+    {
+       var hexCode=idx.toString(16);
+       resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + this.extension;
+       resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
+       hasResultsPage = true;
+    }
+    else // nothing available for this search term
+    {
+       resultsPage = this.resultsPath + '/nomatches' + this.extension;
+       resultsPageWithSearch = resultsPage;
+       hasResultsPage = false;
+    }
+
+    window.frames.MSearchResults.location = resultsPageWithSearch;
+    var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
+
+    if (domPopupSearchResultsWindow.style.display!='block')
+    {
+       var domSearchBox = this.DOMSearchBox();
+       this.DOMSearchClose().style.display = 'inline-block';
+       if (this.insideFrame)
+       {
+         var domPopupSearchResults = this.DOMPopupSearchResults();
+         domPopupSearchResultsWindow.style.position = 'relative';
+         domPopupSearchResultsWindow.style.display  = 'block';
+         var width = document.body.clientWidth - 8; // the -8 is for IE :-(
+         domPopupSearchResultsWindow.style.width    = width + 'px';
+         domPopupSearchResults.style.width          = width + 'px';
+       }
+       else
+       {
+         var domPopupSearchResults = this.DOMPopupSearchResults();
+         var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
+         var top  = getYPos(domSearchBox) + 20;  // domSearchBox.offsetHeight + 1;
+         domPopupSearchResultsWindow.style.display = 'block';
+         left -= domPopupSearchResults.offsetWidth;
+         domPopupSearchResultsWindow.style.top     = top  + 'px';
+         domPopupSearchResultsWindow.style.left    = left + 'px';
+       }
+    }
+
+    this.lastSearchValue = searchValue;
+    this.lastResultsPage = resultsPage;
+  }
+
+  // -------- Activation Functions
+
+  // Activates or deactivates the search panel, resetting things to
+  // their default values if necessary.
+  this.Activate = function(isActive)
+  {
+    if (isActive || // open it
+        this.DOMPopupSearchResultsWindow().style.display == 'block'
+       )
+    {
+      this.DOMSearchBox().className = 'MSearchBoxActive';
+
+      var searchField = this.DOMSearchField();
+
+      if (searchField.value == this.searchLabel) // clear "Search" term upon entry
+      {
+        searchField.value = '';
+        this.searchActive = true;
+      }
+    }
+    else if (!isActive) // directly remove the panel
+    {
+      this.DOMSearchBox().className = 'MSearchBoxInactive';
+      this.DOMSearchField().value   = this.searchLabel;
+      this.searchActive             = false;
+      this.lastSearchValue          = ''
+      this.lastResultsPage          = '';
+    }
+  }
+}
+
+// -----------------------------------------------------------------------
+
+// The class that handles everything on the search results page.
+function SearchResults(name)
+{
+    // The number of matches from the last run of <Search()>.
+    this.lastMatchCount = 0;
+    this.lastKey = 0;
+    this.repeatOn = false;
+
+    // Toggles the visibility of the passed element ID.
+    this.FindChildElement = function(id)
+    {
+      var parentElement = document.getElementById(id);
+      var element = parentElement.firstChild;
+
+      while (element && element!=parentElement)
+      {
+        if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren')
+        {
+          return element;
+        }
+
+        if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes())
+        {
+           element = element.firstChild;
+        }
+        else if (element.nextSibling)
+        {
+           element = element.nextSibling;
+        }
+        else
+        {
+          do
+          {
+            element = element.parentNode;
+          }
+          while (element && element!=parentElement && !element.nextSibling);
+
+          if (element && element!=parentElement)
+          {
+            element = element.nextSibling;
+          }
+        }
+      }
+    }
+
+    this.Toggle = function(id)
+    {
+      var element = this.FindChildElement(id);
+      if (element)
+      {
+        if (element.style.display == 'block')
+        {
+          element.style.display = 'none';
+        }
+        else
+        {
+          element.style.display = 'block';
+        }
+      }
+    }
+
+    // Searches for the passed string.  If there is no parameter,
+    // it takes it from the URL query.
+    //
+    // Always returns true, since other documents may try to call it
+    // and that may or may not be possible.
+    this.Search = function(search)
+    {
+      if (!search) // get search word from URL
+      {
+        search = window.location.search;
+        search = search.substring(1);  // Remove the leading '?'
+        search = unescape(search);
+      }
+
+      search = search.replace(/^ +/, ""); // strip leading spaces
+      search = search.replace(/ +$/, ""); // strip trailing spaces
+      search = search.toLowerCase();
+      search = convertToId(search);
+
+      var resultRows = document.getElementsByTagName("div");
+      var matches = 0;
+
+      var i = 0;
+      while (i < resultRows.length)
+      {
+        var row = resultRows.item(i);
+        if (row.className == "SRResult")
+        {
+          var rowMatchName = row.id.toLowerCase();
+          rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
+
+          if (search.length<=rowMatchName.length &&
+             rowMatchName.substr(0, search.length)==search)
+          {
+            row.style.display = 'block';
+            matches++;
+          }
+          else
+          {
+            row.style.display = 'none';
+          }
+        }
+        i++;
+      }
+      document.getElementById("Searching").style.display='none';
+      if (matches == 0) // no results
+      {
+        document.getElementById("NoMatches").style.display='block';
+      }
+      else // at least one result
+      {
+        document.getElementById("NoMatches").style.display='none';
+      }
+      this.lastMatchCount = matches;
+      return true;
+    }
+
+    // return the first item with index index or higher that is visible
+    this.NavNext = function(index)
+    {
+      var focusItem;
+      while (1)
+      {
+        var focusName = 'Item'+index;
+        focusItem = document.getElementById(focusName);
+        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+        {
+          break;
+        }
+        else if (!focusItem) // last element
+        {
+          break;
+        }
+        focusItem=null;
+        index++;
+      }
+      return focusItem;
+    }
+
+    this.NavPrev = function(index)
+    {
+      var focusItem;
+      while (1)
+      {
+        var focusName = 'Item'+index;
+        focusItem = document.getElementById(focusName);
+        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+        {
+          break;
+        }
+        else if (!focusItem) // last element
+        {
+          break;
+        }
+        focusItem=null;
+        index--;
+      }
+      return focusItem;
+    }
+
+    this.ProcessKeys = function(e)
+    {
+      if (e.type == "keydown")
+      {
+        this.repeatOn = false;
+        this.lastKey = e.keyCode;
+      }
+      else if (e.type == "keypress")
+      {
+        if (!this.repeatOn)
+        {
+          if (this.lastKey) this.repeatOn = true;
+          return false; // ignore first keypress after keydown
+        }
+      }
+      else if (e.type == "keyup")
+      {
+        this.lastKey = 0;
+        this.repeatOn = false;
+      }
+      return this.lastKey!=0;
+    }
+
+    this.Nav = function(evt,itemIndex)
+    {
+      var e  = (evt) ? evt : window.event; // for IE
+      if (e.keyCode==13) return true;
+      if (!this.ProcessKeys(e)) return false;
+
+      if (this.lastKey==38) // Up
+      {
+        var newIndex = itemIndex-1;
+        var focusItem = this.NavPrev(newIndex);
+        if (focusItem)
+        {
+          var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
+          if (child && child.style.display == 'block') // children visible
+          {
+            var n=0;
+            var tmpElem;
+            while (1) // search for last child
+            {
+              tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
+              if (tmpElem)
+              {
+                focusItem = tmpElem;
+              }
+              else // found it!
+              {
+                break;
+              }
+              n++;
+            }
+          }
+        }
+        if (focusItem)
+        {
+          focusItem.focus();
+        }
+        else // return focus to search field
+        {
+           parent.document.getElementById("MSearchField").focus();
+        }
+      }
+      else if (this.lastKey==40) // Down
+      {
+        var newIndex = itemIndex+1;
+        var focusItem;
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem && elem.style.display == 'block') // children visible
+        {
+          focusItem = document.getElementById('Item'+itemIndex+'_c0');
+        }
+        if (!focusItem) focusItem = this.NavNext(newIndex);
+        if (focusItem)  focusItem.focus();
+      }
+      else if (this.lastKey==39) // Right
+      {
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem) elem.style.display = 'block';
+      }
+      else if (this.lastKey==37) // Left
+      {
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem) elem.style.display = 'none';
+      }
+      else if (this.lastKey==27) // Escape
+      {
+        parent.searchBox.CloseResultsWindow();
+        parent.document.getElementById("MSearchField").focus();
+      }
+      else if (this.lastKey==13) // Enter
+      {
+        return true;
+      }
+      return false;
+    }
+
+    this.NavChild = function(evt,itemIndex,childIndex)
+    {
+      var e  = (evt) ? evt : window.event; // for IE
+      if (e.keyCode==13) return true;
+      if (!this.ProcessKeys(e)) return false;
+
+      if (this.lastKey==38) // Up
+      {
+        if (childIndex>0)
+        {
+          var newIndex = childIndex-1;
+          document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
+        }
+        else // already at first child, jump to parent
+        {
+          document.getElementById('Item'+itemIndex).focus();
+        }
+      }
+      else if (this.lastKey==40) // Down
+      {
+        var newIndex = childIndex+1;
+        var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
+        if (!elem) // last child, jump to parent next parent
+        {
+          elem = this.NavNext(itemIndex+1);
+        }
+        if (elem)
+        {
+          elem.focus();
+        }
+      }
+      else if (this.lastKey==27) // Escape
+      {
+        parent.searchBox.CloseResultsWindow();
+        parent.document.getElementById("MSearchField").focus();
+      }
+      else if (this.lastKey==13) // Enter
+      {
+        return true;
+      }
+      return false;
+    }
+}
+
+function setKeyActions(elem,action)
+{
+  elem.setAttribute('onkeydown',action);
+  elem.setAttribute('onkeypress',action);
+  elem.setAttribute('onkeyup',action);
+}
+
+function setClassAttr(elem,attr)
+{
+  elem.setAttribute('class',attr);
+  elem.setAttribute('className',attr);
+}
+
+function createResults()
+{
+  var results = document.getElementById("SRResults");
+  for (var e=0; e<searchData.length; e++)
+  {
+    var id = searchData[e][0];
+    var srResult = document.createElement('div');
+    srResult.setAttribute('id','SR_'+id);
+    setClassAttr(srResult,'SRResult');
+    var srEntry = document.createElement('div');
+    setClassAttr(srEntry,'SREntry');
+    var srLink = document.createElement('a');
+    srLink.setAttribute('id','Item'+e);
+    setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
+    setClassAttr(srLink,'SRSymbol');
+    srLink.innerHTML = searchData[e][1][0];
+    srEntry.appendChild(srLink);
+    if (searchData[e][1].length==2) // single result
+    {
+      srLink.setAttribute('href',searchData[e][1][1][0]);
+      if (searchData[e][1][1][1])
+      {
+       srLink.setAttribute('target','_parent');
+      }
+      var srScope = document.createElement('span');
+      setClassAttr(srScope,'SRScope');
+      srScope.innerHTML = searchData[e][1][1][2];
+      srEntry.appendChild(srScope);
+    }
+    else // multiple results
+    {
+      srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
+      var srChildren = document.createElement('div');
+      setClassAttr(srChildren,'SRChildren');
+      for (var c=0; c<searchData[e][1].length-1; c++)
+      {
+        var srChild = document.createElement('a');
+        srChild.setAttribute('id','Item'+e+'_c'+c);
+        setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
+        setClassAttr(srChild,'SRScope');
+        srChild.setAttribute('href',searchData[e][1][c+1][0]);
+        if (searchData[e][1][c+1][1])
+        {
+         srChild.setAttribute('target','_parent');
+        }
+        srChild.innerHTML = searchData[e][1][c+1][2];
+        srChildren.appendChild(srChild);
+      }
+      srEntry.appendChild(srChildren);
+    }
+    srResult.appendChild(srEntry);
+    results.appendChild(srResult);
+  }
+}
+
+function init_search()
+{
+  var results = document.getElementById("MSearchSelectWindow");
+  for (var key in indexSectionLabels)
+  {
+    var link = document.createElement('a');
+    link.setAttribute('class','SelectItem');
+    link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
+    link.href='javascript:void(0)';
+    link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
+    results.appendChild(link);
+  }
+  searchBox.OnSelectItem(0);
+}
+/* @license-end */
diff --git a/extlib/mimalloc/docs/search/search_l.png b/extlib/mimalloc/docs/search/search_l.png
new file mode 100644 (file)
index 0000000..fd5f7da
Binary files /dev/null and b/extlib/mimalloc/docs/search/search_l.png differ
diff --git a/extlib/mimalloc/docs/search/search_m.png b/extlib/mimalloc/docs/search/search_m.png
new file mode 100644 (file)
index 0000000..b429a16
Binary files /dev/null and b/extlib/mimalloc/docs/search/search_m.png differ
diff --git a/extlib/mimalloc/docs/search/search_r.png b/extlib/mimalloc/docs/search/search_r.png
new file mode 100644 (file)
index 0000000..1af5d21
Binary files /dev/null and b/extlib/mimalloc/docs/search/search_r.png differ
diff --git a/extlib/mimalloc/docs/search/searchdata.js b/extlib/mimalloc/docs/search/searchdata.js
new file mode 100644 (file)
index 0000000..dd31068
--- /dev/null
@@ -0,0 +1,39 @@
+var indexSectionsWithContent =
+{
+  0: "_abcehmoprtuz",
+  1: "m",
+  2: "m",
+  3: "bcru",
+  4: "m",
+  5: "m",
+  6: "_m",
+  7: "abcehprtz",
+  8: "beopu"
+};
+
+var indexSectionNames =
+{
+  0: "all",
+  1: "classes",
+  2: "functions",
+  3: "variables",
+  4: "typedefs",
+  5: "enums",
+  6: "enumvalues",
+  7: "groups",
+  8: "pages"
+};
+
+var indexSectionLabels =
+{
+  0: "All",
+  1: "Data Structures",
+  2: "Functions",
+  3: "Variables",
+  4: "Typedefs",
+  5: "Enumerations",
+  6: "Enumerator",
+  7: "Modules",
+  8: "Pages"
+};
+
diff --git a/extlib/mimalloc/docs/search/typedefs_0.html b/extlib/mimalloc/docs/search/typedefs_0.html
new file mode 100644 (file)
index 0000000..a4684c4
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/typedefs_0.js b/extlib/mimalloc/docs/search/typedefs_0.js
new file mode 100644 (file)
index 0000000..ac67dcd
--- /dev/null
@@ -0,0 +1,8 @@
+var searchData=
+[
+  ['mi_5fblock_5fvisit_5ffun_291',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
+  ['mi_5fdeferred_5ffree_5ffun_292',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
+  ['mi_5ferror_5ffun_293',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5ft_294',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
+  ['mi_5foutput_5ffun_295',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/typedefs_1.html b/extlib/mimalloc/docs/search/typedefs_1.html
new file mode 100644 (file)
index 0000000..c8a0268
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.15"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/typedefs_1.js b/extlib/mimalloc/docs/search/typedefs_1.js
new file mode 100644 (file)
index 0000000..ecccb16
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['heartbeat',['heartbeat',['../group__extended.html#ga411f6e94394a2400aa460c796beff8d8',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/typedefs_2.html b/extlib/mimalloc/docs/search/typedefs_2.html
new file mode 100644 (file)
index 0000000..86a9195
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.15"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/typedefs_2.js b/extlib/mimalloc/docs/search/typedefs_2.js
new file mode 100644 (file)
index 0000000..2af0607
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
+  ['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]]
+];
diff --git a/extlib/mimalloc/docs/search/variables_0.html b/extlib/mimalloc/docs/search/variables_0.html
new file mode 100644 (file)
index 0000000..1e477c0
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/variables_0.js b/extlib/mimalloc/docs/search/variables_0.js
new file mode 100644 (file)
index 0000000..4c0d772
--- /dev/null
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['block_5fsize_286',['block_size',['../group__analysis.html#a332a6c14d736a99699d5453a1cb04b41',1,'mi_heap_area_t']]],
+  ['blocks_287',['blocks',['../group__analysis.html#ae0085e6e1cf059a4eb7767e30e9991b8',1,'mi_heap_area_t']]]
+];
diff --git a/extlib/mimalloc/docs/search/variables_1.html b/extlib/mimalloc/docs/search/variables_1.html
new file mode 100644 (file)
index 0000000..ea73d9a
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/variables_1.js b/extlib/mimalloc/docs/search/variables_1.js
new file mode 100644 (file)
index 0000000..449fd61
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['committed_288',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]]
+];
diff --git a/extlib/mimalloc/docs/search/variables_2.html b/extlib/mimalloc/docs/search/variables_2.html
new file mode 100644 (file)
index 0000000..0580462
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/variables_2.js b/extlib/mimalloc/docs/search/variables_2.js
new file mode 100644 (file)
index 0000000..713c68e
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['reserved_289',['reserved',['../group__analysis.html#ae848a3e6840414891035423948ca0383',1,'mi_heap_area_t']]]
+];
diff --git a/extlib/mimalloc/docs/search/variables_3.html b/extlib/mimalloc/docs/search/variables_3.html
new file mode 100644 (file)
index 0000000..0d69e76
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+</script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+window.addEventListener("message", function(event) {
+  if (event.data == "take_focus") {
+    var elem = searchResults.NavNext(0);
+    if (elem) elem.focus();
+  }
+});
+/* @license-end */
+</script>
+</div>
+</body>
+</html>
diff --git a/extlib/mimalloc/docs/search/variables_3.js b/extlib/mimalloc/docs/search/variables_3.js
new file mode 100644 (file)
index 0000000..08ec3ba
--- /dev/null
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['used_290',['used',['../group__analysis.html#ab820302c5cd0df133eb8e51650a008b4',1,'mi_heap_area_t']]]
+];
diff --git a/extlib/mimalloc/docs/splitbar.png b/extlib/mimalloc/docs/splitbar.png
new file mode 100644 (file)
index 0000000..cce10a7
Binary files /dev/null and b/extlib/mimalloc/docs/splitbar.png differ
diff --git a/extlib/mimalloc/docs/sync_off.png b/extlib/mimalloc/docs/sync_off.png
new file mode 100644 (file)
index 0000000..f3be5ed
Binary files /dev/null and b/extlib/mimalloc/docs/sync_off.png differ
diff --git a/extlib/mimalloc/docs/sync_on.png b/extlib/mimalloc/docs/sync_on.png
new file mode 100644 (file)
index 0000000..b3bab7d
Binary files /dev/null and b/extlib/mimalloc/docs/sync_on.png differ
diff --git a/extlib/mimalloc/docs/tab_a.png b/extlib/mimalloc/docs/tab_a.png
new file mode 100644 (file)
index 0000000..679245f
Binary files /dev/null and b/extlib/mimalloc/docs/tab_a.png differ
diff --git a/extlib/mimalloc/docs/tab_b.png b/extlib/mimalloc/docs/tab_b.png
new file mode 100644 (file)
index 0000000..6b37547
Binary files /dev/null and b/extlib/mimalloc/docs/tab_b.png differ
diff --git a/extlib/mimalloc/docs/tab_h.png b/extlib/mimalloc/docs/tab_h.png
new file mode 100644 (file)
index 0000000..1facf3e
Binary files /dev/null and b/extlib/mimalloc/docs/tab_h.png differ
diff --git a/extlib/mimalloc/docs/tab_s.png b/extlib/mimalloc/docs/tab_s.png
new file mode 100644 (file)
index 0000000..69a97a0
Binary files /dev/null and b/extlib/mimalloc/docs/tab_s.png differ
diff --git a/extlib/mimalloc/docs/tabs.css b/extlib/mimalloc/docs/tabs.css
new file mode 100644 (file)
index 0000000..e1f2e0b
--- /dev/null
@@ -0,0 +1,61 @@
+.tabs, .tabs2, .tabs3 {
+    background-image: url('tab_b.png');
+    width: 100%;
+    z-index: 101;
+    font-size: 13px;
+    font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+}
+
+.tabs2 {
+    font-size: 10px;
+}
+.tabs3 {
+    font-size: 9px;
+}
+
+.tablist {
+    margin: 0;
+    padding: 0;
+    display: table;
+}
+
+.tablist li {
+    float: left;
+    display: table-cell;
+    background-image: url('tab_b.png');
+    line-height: 36px;
+    list-style: none;
+}
+
+.tablist a {
+    display: block;
+    padding: 0 20px;
+    font-weight: bold;
+    background-image:url('tab_s.png');
+    background-repeat:no-repeat;
+    background-position:right;
+    color: #040404;
+    text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+    text-decoration: none;
+    outline: none;
+}
+
+.tabs3 .tablist a {
+    padding: 0 10px;
+}
+
+.tablist a:hover {
+    background-image: url('tab_h.png');
+    background-repeat:repeat-x;
+    color: #fff;
+    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
+    text-decoration: none;
+}
+
+.tablist li.current a {
+    background-image: url('tab_a.png');
+    background-repeat:repeat-x;
+    color: #fff;
+    text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0);
+}
+
diff --git a/extlib/mimalloc/docs/using.html b/extlib/mimalloc/docs/using.html
new file mode 100644 (file)
index 0000000..140f0c5
--- /dev/null
@@ -0,0 +1,155 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.9.1"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>mi-malloc: Using the library</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="navtree.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="resize.js"></script>
+<script type="text/javascript" src="navtreedata.js"></script>
+<script type="text/javascript" src="navtree.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+  $(document).ready(function() { init_search(); });
+/* @license-end */
+</script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">mi-malloc
+   &#160;<span id="projectnumber">1.7/2.0</span>
+   </div>
+  </td>
+   <td>        <div id="MSearchBox" class="MSearchBoxInactive">
+        <span class="left">
+          <img id="MSearchSelect" src="search/mag_sel.svg"
+               onmouseover="return searchBox.OnSearchSelectShow()"
+               onmouseout="return searchBox.OnSearchSelectHide()"
+               alt=""/>
+          <input type="text" id="MSearchField" value="Search" accesskey="S"
+               onfocus="searchBox.OnSearchFieldFocus(true)" 
+               onblur="searchBox.OnSearchFieldFocus(false)" 
+               onkeyup="searchBox.OnSearchFieldChange(event)"/>
+          </span><span class="right">
+            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
+          </span>
+        </div>
+</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.9.1 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
+/* @license-end */
+</script>
+</div><!-- top -->
+<div id="side-nav" class="ui-resizable side-nav-resizable">
+  <div id="nav-tree">
+    <div id="nav-tree-contents">
+      <div id="nav-sync" class="sync"></div>
+    </div>
+  </div>
+  <div id="splitbar" style="-moz-user-select:none;" 
+       class="ui-resizable-handle">
+  </div>
+</div>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(document).ready(function(){initNavTree('using.html',''); initResizable(); });
+/* @license-end */
+</script>
+<div id="doc-content">
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Using the library </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><h3>Build</h3>
+<p>The preferred usage is including <code>&lt;mimalloc.h&gt;</code>, linking with the shared- or static library, and using the <code>mi_malloc</code> API exclusively for allocation. For example, </p><div class="fragment"><div class="line">gcc -o myprogram -lmimalloc myfile.c</div>
+</div><!-- fragment --><p>mimalloc uses only safe OS calls (<code>mmap</code> and <code>VirtualAlloc</code>) and can co-exist with other allocators linked to the same program. If you use <code>cmake</code>, you can simply use: </p><div class="fragment"><div class="line">find_package(mimalloc 1.0 REQUIRED)</div>
+</div><!-- fragment --><p> in your <code>CMakeLists.txt</code> to find a locally installed mimalloc. Then use either: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc)</div>
+</div><!-- fragment --><p> to link with the shared (dynamic) library, or: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc-<span class="keyword">static</span>)</div>
+</div><!-- fragment --><p> to link with the static library. See <code>test\CMakeLists.txt</code> for an example.</p>
+<h3>C++</h3>
+<p>For best performance in C++ programs, it is also recommended to override the global <code>new</code> and <code>delete</code> operators. For convience, mimalloc provides <a href="https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h"><code>mimalloc-new-delete.h</code></a> which does this for you &ndash; just include it in a single(!) source file in your project without linking to the mimalloc's library.</p>
+<p>In C++, mimalloc also provides the <code><a class="el" href="group__cpp.html#structmi__stl__allocator" title="std::allocator implementation for mimalloc for use in STL containers.">mi_stl_allocator</a></code> struct which implements the <code>std::allocator</code> interface. For example: </p><div class="fragment"><div class="line">std::vector&lt;some_struct, mi_stl_allocator&lt;some_struct&gt;&gt; vec;</div>
+<div class="line">vec.push_back(some_struct());</div>
+</div><!-- fragment --><h3>Statistics</h3>
+<p>You can pass environment variables to print verbose messages (<code>MIMALLOC_VERBOSE=1</code>) and statistics (<code>MIMALLOC_SHOW_STATS=1</code>) (in the debug version): </p><div class="fragment"><div class="line">&gt; env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363</div>
+<div class="line"> </div>
+<div class="line">175451865205073170563711388363 = 374456281610909315237213 * 468551</div>
+<div class="line"> </div>
+<div class="line">heap stats:     peak      total      freed       unit</div>
+<div class="line">normal   2:    16.4 kb    17.5 mb    17.5 mb      16 b   ok</div>
+<div class="line">normal   3:    16.3 kb    15.2 mb    15.2 mb      24 b   ok</div>
+<div class="line">normal   4:      64 b      4.6 kb     4.6 kb      32 b   ok</div>
+<div class="line">normal   5:      80 b    118.4 kb   118.4 kb      40 b   ok</div>
+<div class="line">normal   6:      48 b       48 b       48 b       48 b   ok</div>
+<div class="line">normal  17:     960 b      960 b      960 b      320 b   ok</div>
+<div class="line"> </div>
+<div class="line">heap stats:     peak      total      freed       unit</div>
+<div class="line">    normal:    33.9 kb    32.8 mb    32.8 mb       1 b   ok</div>
+<div class="line">      huge:       0 b        0 b        0 b        1 b   ok</div>
+<div class="line">     total:    33.9 kb    32.8 mb    32.8 mb       1 b   ok</div>
+<div class="line">malloc requested:         32.8 mb</div>
+<div class="line"> </div>
+<div class="line"> committed:    58.2 kb    58.2 kb    58.2 kb       1 b   ok</div>
+<div class="line">  reserved:     2.0 mb     2.0 mb     2.0 mb       1 b   ok</div>
+<div class="line">     reset:       0 b        0 b        0 b        1 b   ok</div>
+<div class="line">  segments:       1          1          1</div>
+<div class="line">-abandoned:       0</div>
+<div class="line">     pages:       6          6          6</div>
+<div class="line">-abandoned:       0</div>
+<div class="line">     mmaps:       3</div>
+<div class="line"> mmap fast:       0</div>
+<div class="line"> mmap slow:       1</div>
+<div class="line">   threads:       0</div>
+<div class="line">   elapsed:     2.022s</div>
+<div class="line">   process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb</div>
+</div><!-- fragment --><p>The above model of using the <code>mi_</code> prefixed API is not always possible though in existing programs that already use the standard malloc interface, and another option is to override the standard malloc interface completely and redirect all calls to the <em>mimalloc</em> library instead.</p>
+<p>See <a class="el" href="overrides.html">Overriding Malloc</a> for more info. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+</div><!-- doc-content -->
+<!-- start footer part -->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+  <ul>
+    <li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1 </li>
+  </ul>
+</div>
+</body>
+</html>
index 990d6ca97201b26ce6709d24795c031fdba951d1..a87b69ac6887747354fc8b4e2672e8a18c666dac 100644 (file)
     <ClInclude Include="..\..\include\mimalloc-new-delete.h" />
     <ClInclude Include="..\..\include\mimalloc-override.h" />
     <ClInclude Include="..\..\include\mimalloc-types.h" />
+    <ClInclude Include="..\..\src\bitmap.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\alloc-aligned.c">
     <ClCompile Include="..\..\src\alloc-posix.c" />
     <ClCompile Include="..\..\src\alloc.c" />
     <ClCompile Include="..\..\src\arena.c" />
+    <ClCompile Include="..\..\src\bitmap.c" />
     <ClCompile Include="..\..\src\heap.c" />
     <ClCompile Include="..\..\src\init.c" />
-    <ClCompile Include="..\..\src\region.c" />
     <ClCompile Include="..\..\src\options.c" />
     <ClCompile Include="..\..\src\os.c" />
     <ClCompile Include="..\..\src\page-queue.c">
     </ClCompile>
     <ClCompile Include="..\..\src\page.c" />
     <ClCompile Include="..\..\src\random.c" />
+    <ClCompile Include="..\..\src\segment-cache.c" />
     <ClCompile Include="..\..\src\segment.c" />
     <ClCompile Include="..\..\src\stats.c" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
index 026526580a6bdcbcf0e272b02699f112693e85e5..d01f9311f199db8446fdbf1c8aa62826794ccedc 100644 (file)
@@ -29,6 +29,9 @@
     <ClInclude Include="..\..\include\mimalloc-new-delete.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\bitmap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\alloc.c">
@@ -61,9 +64,6 @@
     <ClCompile Include="..\..\src\init.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\region.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\alloc-override.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\random.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\bitmap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\segment-cache.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
index 770a87b25ac1cf732e6438734c830f9fff6084d2..41fb77c1bf237b73735b51104c771d9d838e4e70 100644 (file)
       <ConformanceMode>true</ConformanceMode>
       <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
-      <CompileAs>CompileAsCpp</CompileAs>
+      <CompileAs>CompileAsC</CompileAs>
       <SupportJustMyCode>false</SupportJustMyCode>
       <LanguageStandard>stdcpp17</LanguageStandard>
     </ClCompile>
       <ConformanceMode>true</ConformanceMode>
       <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
-      <CompileAs>CompileAsCpp</CompileAs>
+      <CompileAs>CompileAsC</CompileAs>
       <SupportJustMyCode>false</SupportJustMyCode>
       <LanguageStandard>stdcpp17</LanguageStandard>
     </ClCompile>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
-      <CompileAs>CompileAsCpp</CompileAs>
+      <CompileAs>CompileAsC</CompileAs>
       <IntrinsicFunctions>true</IntrinsicFunctions>
     </ClCompile>
     <Link>
       <WholeProgramOptimization>false</WholeProgramOptimization>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <InlineFunctionExpansion>Default</InlineFunctionExpansion>
-      <CompileAs>CompileAsCpp</CompileAs>
+      <CompileAs>CompileAsC</CompileAs>
       <IntrinsicFunctions>true</IntrinsicFunctions>
     </ClCompile>
     <Link>
     <ClCompile Include="..\..\src\alloc-posix.c" />
     <ClCompile Include="..\..\src\alloc.c" />
     <ClCompile Include="..\..\src\arena.c" />
+    <ClCompile Include="..\..\src\bitmap.c" />
     <ClCompile Include="..\..\src\heap.c" />
     <ClCompile Include="..\..\src\init.c" />
-    <ClCompile Include="..\..\src\region.c" />
     <ClCompile Include="..\..\src\options.c" />
     <ClCompile Include="..\..\src\page-queue.c">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
     </ClCompile>
     <ClCompile Include="..\..\src\page.c" />
     <ClCompile Include="..\..\src\random.c" />
+    <ClCompile Include="..\..\src\segment-cache.c" />
     <ClCompile Include="..\..\src\segment.c" />
     <ClCompile Include="..\..\src\os.c" />
     <ClCompile Include="..\..\src\stats.c" />
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h" />
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h" />
     <ClInclude Include="..\..\include\mimalloc-new-delete.h" />
+    <ClInclude Include="..\..\src\bitmap.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
index 43660519aed9fd8bd13de4b6ab52ece981abbab1..05417645268664cf3dcbb2730a1108a1665020ee 100644 (file)
     <ClCompile Include="..\..\src\init.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\region.c">
+    <ClCompile Include="..\..\src\alloc-posix.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\alloc-posix.c">
+    <ClCompile Include="..\..\src\arena.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\arena.c">
     <ClCompile Include="..\..\src\random.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\bitmap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\segment-cache.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h">
@@ -79,5 +85,8 @@
     <ClInclude Include="..\..\include\mimalloc-new-delete.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\bitmap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
index a0e79fb06ca96bfa4fdd58715253d9f093ef18ec..4136e574a83c3f63c1d7c565288bd40c2e7114c7 100644 (file)
     <ClInclude Include="..\..\include\mimalloc-new-delete.h" />
     <ClInclude Include="..\..\include\mimalloc-override.h" />
     <ClInclude Include="..\..\include\mimalloc-types.h" />
+    <ClInclude Include="..\..\src\bitmap.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\alloc-aligned.c">
     <ClCompile Include="..\..\src\alloc-posix.c" />
     <ClCompile Include="..\..\src\alloc.c" />
     <ClCompile Include="..\..\src\arena.c" />
-    <ClCompile Include="..\..\src\bitmap.inc.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
-    </ClCompile>
+    <ClCompile Include="..\..\src\bitmap.c" />
     <ClCompile Include="..\..\src\heap.c" />
     <ClCompile Include="..\..\src\init.c" />
-    <ClCompile Include="..\..\src\region.c" />
     <ClCompile Include="..\..\src\options.c" />
     <ClCompile Include="..\..\src\os.c" />
     <ClCompile Include="..\..\src\page-queue.c">
     </ClCompile>
     <ClCompile Include="..\..\src\page.c" />
     <ClCompile Include="..\..\src\random.c" />
+    <ClCompile Include="..\..\src\segment-cache.c" />
     <ClCompile Include="..\..\src\segment.c" />
     <ClCompile Include="..\..\src\stats.c" />
   </ItemGroup>
index 8e36f50e8538f145e93baa634e63e0d7c67b1917..d6b7b5a966df0faed97dc6856341fcae584b3edd 100644 (file)
@@ -19,9 +19,6 @@
     <ClCompile Include="..\..\src\init.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\region.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\os.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\arena.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\bitmap.inc.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\random.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\options.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\bitmap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\segment-cache.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h">
@@ -69,6 +69,9 @@
     <ClInclude Include="..\..\include\mimalloc-types.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\bitmap.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Header Files">
index afbb6666619bcbc52500c0133a5c5bc56582710b..ef7ab3575a963d09a039e4536f720fe742cba9a1 100644 (file)
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="mimalloc-override.vcxproj">
-      <Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project>
+    <ProjectReference Include="mimalloc.vcxproj">
+      <Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
     </ProjectReference>
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
index e18db0c5c87f30540a0fd13a76699251a95c5b7d..9f967d94464baeb99ba10d9987696d96591bbb61 100644 (file)
@@ -92,7 +92,7 @@
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
+      <WarningLevel>Level4</WarningLevel>
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
       <ConformanceMode>true</ConformanceMode>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
+      <WarningLevel>Level4</WarningLevel>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <ConformanceMode>true</ConformanceMode>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
+      <WarningLevel>Level4</WarningLevel>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <ConformanceMode>true</ConformanceMode>
     <ClCompile Include="..\..\src\alloc-posix.c" />
     <ClCompile Include="..\..\src\alloc.c" />
     <ClCompile Include="..\..\src\arena.c" />
-    <ClCompile Include="..\..\src\bitmap.inc.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
+    <ClCompile Include="..\..\src\bitmap.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
     </ClCompile>
     <ClCompile Include="..\..\src\heap.c" />
     <ClCompile Include="..\..\src\init.c" />
-    <ClCompile Include="..\..\src\region.c" />
     <ClCompile Include="..\..\src\options.c" />
     <ClCompile Include="..\..\src\page-queue.c">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
     </ClCompile>
     <ClCompile Include="..\..\src\page.c" />
     <ClCompile Include="..\..\src\random.c" />
+    <ClCompile Include="..\..\src\segment-cache.c" />
     <ClCompile Include="..\..\src\segment.c" />
     <ClCompile Include="..\..\src\os.c" />
     <ClCompile Include="..\..\src\stats.c" />
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h" />
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h" />
     <ClInclude Include="..\..\include\mimalloc-new-delete.h" />
+    <ClInclude Include="..\..\src\bitmap.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
index 4704fb2ec9bc0537fdc252d46065c5c85a9bb7a1..92be7cb47e81e4141cd5900690c11d7126af0b78 100644 (file)
@@ -22,9 +22,6 @@
     <ClCompile Include="..\..\src\init.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\region.c">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\options.c">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\arena.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\bitmap.inc.c">
+    <ClCompile Include="..\..\src\random.c">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\random.c">
+    <ClCompile Include="..\..\src\bitmap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\segment-cache.c">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>
@@ -72,6 +72,9 @@
     <ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\bitmap.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Header Files">
@@ -81,4 +84,4 @@
       <UniqueIdentifier>{852a14ae-6dde-4e95-8077-ca705e97e5af}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
index 722b6ad659a4ffddacc0494317b92416ec839cd6..7ad5da585133645bcc37b2109acdba0050c30747 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021 Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -8,125 +8,121 @@ terms of the MIT license. A copy of the license can be found in the file
 #ifndef MIMALLOC_ATOMIC_H
 #define MIMALLOC_ATOMIC_H
 
-// ------------------------------------------------------
+// --------------------------------------------------------------------------------------------
 // Atomics
 // We need to be portable between C, C++, and MSVC.
-// ------------------------------------------------------
+// We base the primitives on the C/C++ atomics and create a mimimal wrapper for MSVC in C compilation mode. 
+// This is why we try to use only `uintptr_t` and `<type>*` as atomic types. 
+// To gain better insight in the range of used atomics, we use explicitly named memory order operations 
+// instead of passing the memory order as a parameter.
+// -----------------------------------------------------------------------------------------------
 
-#if defined(_MSC_VER)
-#define _Atomic(tp)         tp
-#define ATOMIC_VAR_INIT(x)  x
-#elif defined(__cplusplus)
+#if defined(__cplusplus)
+// Use C++ atomics
 #include <atomic>
-#define  _Atomic(tp)        std::atomic<tp>
+#define  _Atomic(tp)            std::atomic<tp>
+#define  mi_atomic(name)        std::atomic_##name
+#define  mi_memory_order(name)  std::memory_order_##name
+#if !defined(ATOMIC_VAR_INIT) || (__cplusplus >= 202002L) // c++20, see issue #571
+ #define MI_ATOMIC_VAR_INIT(x)  x
+#else
+ #define MI_ATOMIC_VAR_INIT(x)  ATOMIC_VAR_INIT(x)
+#endif
+#elif defined(_MSC_VER)
+// Use MSVC C wrapper for C11 atomics
+#define  _Atomic(tp)            tp 
+#define  MI_ATOMIC_VAR_INIT(x)  x
+#define  mi_atomic(name)        mi_atomic_##name
+#define  mi_memory_order(name)  mi_memory_order_##name
 #else
+// Use C11 atomics
 #include <stdatomic.h>
+#define  mi_atomic(name)        atomic_##name
+#define  mi_memory_order(name)  memory_order_##name
+#define  MI_ATOMIC_VAR_INIT(x)  ATOMIC_VAR_INIT(x)
 #endif
 
-// ------------------------------------------------------
-// Atomic operations specialized for mimalloc
-// ------------------------------------------------------
-
-// Atomically add a value; returns the previous value. Memory ordering is relaxed.
-static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add);
-
-// Atomically "and" a value; returns the previous value. Memory ordering is relaxed.
-static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x);
-
-// Atomically "or" a value; returns the previous value. Memory ordering is relaxed.
-static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x);
-
-// Atomically compare and exchange a value; returns `true` if successful.
-// May fail spuriously. Memory ordering as release on success, and relaxed on failure.
-// (Note: expected and desired are in opposite order from atomic_compare_exchange)
-static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected);
+// Various defines for all used memory orders in mimalloc
+#define mi_atomic_cas_weak(p,expected,desired,mem_success,mem_fail)  \
+  mi_atomic(compare_exchange_weak_explicit)(p,expected,desired,mem_success,mem_fail)
+
+#define mi_atomic_cas_strong(p,expected,desired,mem_success,mem_fail)  \
+  mi_atomic(compare_exchange_strong_explicit)(p,expected,desired,mem_success,mem_fail)
+
+#define mi_atomic_load_acquire(p)                mi_atomic(load_explicit)(p,mi_memory_order(acquire))
+#define mi_atomic_load_relaxed(p)                mi_atomic(load_explicit)(p,mi_memory_order(relaxed))
+#define mi_atomic_store_release(p,x)             mi_atomic(store_explicit)(p,x,mi_memory_order(release))
+#define mi_atomic_store_relaxed(p,x)             mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed))
+#define mi_atomic_exchange_release(p,x)          mi_atomic(exchange_explicit)(p,x,mi_memory_order(release))
+#define mi_atomic_exchange_acq_rel(p,x)          mi_atomic(exchange_explicit)(p,x,mi_memory_order(acq_rel))
+#define mi_atomic_cas_weak_release(p,exp,des)    mi_atomic_cas_weak(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed))
+#define mi_atomic_cas_weak_acq_rel(p,exp,des)    mi_atomic_cas_weak(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire))
+#define mi_atomic_cas_strong_release(p,exp,des)  mi_atomic_cas_strong(p,exp,des,mi_memory_order(release),mi_memory_order(relaxed))
+#define mi_atomic_cas_strong_acq_rel(p,exp,des)  mi_atomic_cas_strong(p,exp,des,mi_memory_order(acq_rel),mi_memory_order(acquire))
+
+#define mi_atomic_add_relaxed(p,x)               mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(relaxed))
+#define mi_atomic_sub_relaxed(p,x)               mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(relaxed))
+#define mi_atomic_add_acq_rel(p,x)               mi_atomic(fetch_add_explicit)(p,x,mi_memory_order(acq_rel))
+#define mi_atomic_sub_acq_rel(p,x)               mi_atomic(fetch_sub_explicit)(p,x,mi_memory_order(acq_rel))
+#define mi_atomic_and_acq_rel(p,x)               mi_atomic(fetch_and_explicit)(p,x,mi_memory_order(acq_rel))
+#define mi_atomic_or_acq_rel(p,x)                mi_atomic(fetch_or_explicit)(p,x,mi_memory_order(acq_rel))
+
+#define mi_atomic_increment_relaxed(p)           mi_atomic_add_relaxed(p,(uintptr_t)1)
+#define mi_atomic_decrement_relaxed(p)           mi_atomic_sub_relaxed(p,(uintptr_t)1)
+#define mi_atomic_increment_acq_rel(p)           mi_atomic_add_acq_rel(p,(uintptr_t)1)
+#define mi_atomic_decrement_acq_rel(p)           mi_atomic_sub_acq_rel(p,(uintptr_t)1)
 
-// Atomically compare and exchange a value; returns `true` if successful.
-// Memory ordering is acquire-release
-// (Note: expected and desired are in opposite order from atomic_compare_exchange)
-static inline bool mi_atomic_cas_strong(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected);
-
-// Atomically exchange a value. Memory ordering is acquire-release.
-static inline uintptr_t mi_atomic_exchange(volatile _Atomic(uintptr_t)* p, uintptr_t exchange);
-
-// Atomically read a value. Memory ordering is relaxed.
-static inline uintptr_t mi_atomic_read_relaxed(const volatile _Atomic(uintptr_t)* p);
-
-// Atomically read a value. Memory ordering is acquire.
-static inline uintptr_t mi_atomic_read(const volatile _Atomic(uintptr_t)* p);
-
-// Atomically write a value. Memory ordering is release.
-static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x);
-
-// Yield
 static inline void mi_atomic_yield(void);
+static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add);
+static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub);
 
-// Atomically add a 64-bit value; returns the previous value.
-// Note: not using _Atomic(int64_t) as it is only used for statistics.
-static inline void mi_atomic_addi64(volatile int64_t* p, int64_t add);
-
-// Atomically update `*p` with the maximum of `*p` and `x` as a 64-bit value.
-// Returns the previous value. Note: not using _Atomic(int64_t) as it is only used for statistics.
-static inline void mi_atomic_maxi64(volatile int64_t* p, int64_t x);
 
-// Atomically read a 64-bit value
-// Note: not using _Atomic(int64_t) as it is only used for statistics.
-static inline int64_t mi_atomic_readi64(volatile int64_t* p);
+#if defined(__cplusplus) || !defined(_MSC_VER)
 
-// Atomically subtract a value; returns the previous value.
-static inline uintptr_t mi_atomic_sub(volatile _Atomic(uintptr_t)* p, uintptr_t sub) {
-  return mi_atomic_add(p, (uintptr_t)(-((intptr_t)sub)));
-}
+// In C++/C11 atomics we have polymorphic atomics so can use the typed `ptr` variants (where `tp` is the type of atomic value)
+// We use these macros so we can provide a typed wrapper in MSVC in C compilation mode as well
+#define mi_atomic_load_ptr_acquire(tp,p)                mi_atomic_load_acquire(p)
+#define mi_atomic_load_ptr_relaxed(tp,p)                mi_atomic_load_relaxed(p)
 
-// Atomically increment a value; returns the incremented result.
-static inline uintptr_t mi_atomic_increment(volatile _Atomic(uintptr_t)* p) {
-  return mi_atomic_add(p, 1);
-}
+// In C++ we need to add casts to help resolve templates if NULL is passed
+#if defined(__cplusplus)
+#define mi_atomic_store_ptr_release(tp,p,x)             mi_atomic_store_release(p,(tp*)x)
+#define mi_atomic_store_ptr_relaxed(tp,p,x)             mi_atomic_store_relaxed(p,(tp*)x)
+#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des)    mi_atomic_cas_weak_release(p,exp,(tp*)des)
+#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des)    mi_atomic_cas_weak_acq_rel(p,exp,(tp*)des)
+#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des)  mi_atomic_cas_strong_release(p,exp,(tp*)des)
+#define mi_atomic_exchange_ptr_release(tp,p,x)          mi_atomic_exchange_release(p,(tp*)x)
+#define mi_atomic_exchange_ptr_acq_rel(tp,p,x)          mi_atomic_exchange_acq_rel(p,(tp*)x)
+#else
+#define mi_atomic_store_ptr_release(tp,p,x)             mi_atomic_store_release(p,x)
+#define mi_atomic_store_ptr_relaxed(tp,p,x)             mi_atomic_store_relaxed(p,x)
+#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des)    mi_atomic_cas_weak_release(p,exp,des)
+#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des)    mi_atomic_cas_weak_acq_rel(p,exp,des)
+#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des)  mi_atomic_cas_strong_release(p,exp,des)
+#define mi_atomic_exchange_ptr_release(tp,p,x)          mi_atomic_exchange_release(p,x)
+#define mi_atomic_exchange_ptr_acq_rel(tp,p,x)          mi_atomic_exchange_acq_rel(p,x)
+#endif
 
-// Atomically decrement a value; returns the decremented result.
-static inline uintptr_t mi_atomic_decrement(volatile _Atomic(uintptr_t)* p) {
-  return mi_atomic_sub(p, 1);
+// These are used by the statistics
+static inline int64_t mi_atomic_addi64_relaxed(volatile int64_t* p, int64_t add) {
+  return mi_atomic(fetch_add_explicit)((_Atomic(int64_t)*)p, add, mi_memory_order(relaxed));
 }
-
-// Atomically add a signed value; returns the previous value.
-static inline intptr_t mi_atomic_addi(volatile _Atomic(intptr_t)* p, intptr_t add) {
-  return (intptr_t)mi_atomic_add((volatile _Atomic(uintptr_t)*)p, (uintptr_t)add);
+static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) {
+  int64_t current = mi_atomic_load_relaxed((_Atomic(int64_t)*)p);
+  while (current < x && !mi_atomic_cas_weak_release((_Atomic(int64_t)*)p, &current, x)) { /* nothing */ };
 }
 
-// Atomically subtract a signed value; returns the previous value.
-static inline intptr_t mi_atomic_subi(volatile _Atomic(intptr_t)* p, intptr_t sub) {
-  return (intptr_t)mi_atomic_addi(p,-sub);
-}
-
-// Atomically read a pointer; Memory order is relaxed (i.e. no fence, only atomic).
-#define mi_atomic_read_ptr_relaxed(T,p)  \
-  (T*)(mi_atomic_read_relaxed((const volatile _Atomic(uintptr_t)*)(p)))
+// Used by timers
+#define mi_atomic_loadi64_acquire(p)    mi_atomic(load_explicit)(p,mi_memory_order(acquire))
+#define mi_atomic_loadi64_relaxed(p)    mi_atomic(load_explicit)(p,mi_memory_order(relaxed))
+#define mi_atomic_storei64_release(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(release))
+#define mi_atomic_storei64_relaxed(p,x) mi_atomic(store_explicit)(p,x,mi_memory_order(relaxed))
 
-// Atomically read a pointer; Memory order is acquire.
-#define mi_atomic_read_ptr(T,p) \
-  (T*)(mi_atomic_read((const volatile _Atomic(uintptr_t)*)(p)))
 
-// Atomically write a pointer; Memory order is acquire.
-#define mi_atomic_write_ptr(T,p,x) \
-  mi_atomic_write((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)x))
 
-// Atomically compare and exchange a pointer; returns `true` if successful. May fail spuriously.
-// Memory order is release. (like a write)
-// (Note: expected and desired are in opposite order from atomic_compare_exchange)
-#define mi_atomic_cas_ptr_weak(T,p,desired,expected) \
-  mi_atomic_cas_weak((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)(desired)), (uintptr_t)((T*)(expected)))
-    
-// Atomically compare and exchange a pointer; returns `true` if successful. Memory order is acquire_release.
-// (Note: expected and desired are in opposite order from atomic_compare_exchange)
-#define mi_atomic_cas_ptr_strong(T,p,desired,expected) \
-  mi_atomic_cas_strong((volatile _Atomic(uintptr_t)*)(p),(uintptr_t)((T*)(desired)), (uintptr_t)((T*)(expected))) 
+#elif defined(_MSC_VER)
 
-// Atomically exchange a pointer value.
-#define mi_atomic_exchange_ptr(T,p,exchange) \
-  (T*)mi_atomic_exchange((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)exchange))
-
-
-#ifdef _MSC_VER
+// MSVC C compilation wrapper that uses Interlocked operations to model C11 atomics.
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <intrin.h>
@@ -137,158 +133,206 @@ typedef LONG64   msc_intptr_t;
 typedef LONG     msc_intptr_t;
 #define MI_64(f) f
 #endif
-static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add) {
+
+typedef enum mi_memory_order_e {
+  mi_memory_order_relaxed,
+  mi_memory_order_consume,
+  mi_memory_order_acquire,
+  mi_memory_order_release,
+  mi_memory_order_acq_rel,
+  mi_memory_order_seq_cst
+} mi_memory_order;
+
+static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) {
+  (void)(mo);
   return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add);
 }
-static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
+static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) {
+  (void)(mo);
+  return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub));
+}
+static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
+  (void)(mo);
   return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
 }
-static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
+static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
+  (void)(mo);
   return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
 }
-static inline bool mi_atomic_cas_strong(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
-  return (expected == (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)expected));
+static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) {
+  (void)(mo1); (void)(mo2);
+  uintptr_t read = (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected));
+  if (read == *expected) {
+    return true;
+  }
+  else {
+    *expected = read;
+    return false;
+  }
 }
-static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
-  return mi_atomic_cas_strong(p,desired,expected);
+static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) {
+  return mi_atomic_compare_exchange_strong_explicit(p, expected, desired, mo1, mo2);
 }
-static inline uintptr_t mi_atomic_exchange(volatile _Atomic(uintptr_t)* p, uintptr_t exchange) {
+static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) {
+  (void)(mo);
   return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange);
 }
-static inline uintptr_t mi_atomic_read(volatile _Atomic(uintptr_t) const* p) {
-  return *p;
+static inline void mi_atomic_thread_fence(mi_memory_order mo) {
+  (void)(mo);
+  _Atomic(uintptr_t) x = 0;
+  mi_atomic_exchange_explicit(&x, 1, mo);
 }
-static inline uintptr_t mi_atomic_read_relaxed(volatile _Atomic(uintptr_t) const* p) {
+static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) {
+  (void)(mo);
+#if defined(_M_IX86) || defined(_M_X64)
   return *p;
+#else
+  uintptr_t x = *p;
+  if (mo > mi_memory_order_relaxed) {
+    while (!mi_atomic_compare_exchange_weak_explicit(p, &x, x, mo, mi_memory_order_relaxed)) { /* nothing */ };
+  }
+  return x;
+#endif
 }
-static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
-  #if defined(_M_IX86) || defined(_M_X64)
+static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
+  (void)(mo);
+#if defined(_M_IX86) || defined(_M_X64)
   *p = x;
-  #else
-  mi_atomic_exchange(p,x);
-  #endif
+#else
+  mi_atomic_exchange_explicit(p, x, mo);
+#endif
 }
-static inline void mi_atomic_yield(void) {
-  YieldProcessor();
+static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) {
+  (void)(mo);
+#if defined(_M_X64)
+  return *p;
+#else
+  int64_t old = *p;
+  int64_t x = old;
+  while ((old = InterlockedCompareExchange64(p, x, old)) != x) {
+    x = old;
+  }
+  return x;
+#endif
+}
+static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) {
+  (void)(mo);
+#if defined(x_M_IX86) || defined(_M_X64)
+  *p = x;
+#else
+  InterlockedExchange64(p, x);
+#endif
 }
-static inline void mi_atomic_addi64(volatile _Atomic(int64_t)* p, int64_t add) {
-  #ifdef _WIN64
-  mi_atomic_addi(p,add);
-  #else
+
+// These are used by the statistics
+static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) {
+#ifdef _WIN64
+  return (int64_t)mi_atomic_addi((int64_t*)p, add);
+#else
   int64_t current;
   int64_t sum;
   do {
     current = *p;
     sum = current + add;
   } while (_InterlockedCompareExchange64(p, sum, current) != current);
-  #endif
+  return current;
+#endif
 }
-
-static inline void mi_atomic_maxi64(volatile _Atomic(int64_t)*p, int64_t x) {
+static inline void mi_atomic_maxi64_relaxed(volatile _Atomic(int64_t)*p, int64_t x) {
   int64_t current;
   do {
     current = *p;
   } while (current < x && _InterlockedCompareExchange64(p, x, current) != current);
 }
 
-static inline int64_t mi_atomic_readi64(volatile _Atomic(int64_t)*p) {
-  #ifdef _WIN64
-  return *p;
-  #else
-  int64_t current;
-  do {
-    current = *p;
-  } while (_InterlockedCompareExchange64(p, current, current) != current);
-  return current;
-  #endif
-}
+// The pointer macros cast to `uintptr_t`.
+#define mi_atomic_load_ptr_acquire(tp,p)                (tp*)mi_atomic_load_acquire((_Atomic(uintptr_t)*)(p))
+#define mi_atomic_load_ptr_relaxed(tp,p)                (tp*)mi_atomic_load_relaxed((_Atomic(uintptr_t)*)(p))
+#define mi_atomic_store_ptr_release(tp,p,x)             mi_atomic_store_release((_Atomic(uintptr_t)*)(p),(uintptr_t)(x))
+#define mi_atomic_store_ptr_relaxed(tp,p,x)             mi_atomic_store_relaxed((_Atomic(uintptr_t)*)(p),(uintptr_t)(x))
+#define mi_atomic_cas_ptr_weak_release(tp,p,exp,des)    mi_atomic_cas_weak_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des)
+#define mi_atomic_cas_ptr_weak_acq_rel(tp,p,exp,des)    mi_atomic_cas_weak_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des)
+#define mi_atomic_cas_ptr_strong_release(tp,p,exp,des)  mi_atomic_cas_strong_release((_Atomic(uintptr_t)*)(p),(uintptr_t*)exp,(uintptr_t)des)
+#define mi_atomic_exchange_ptr_release(tp,p,x)          (tp*)mi_atomic_exchange_release((_Atomic(uintptr_t)*)(p),(uintptr_t)x)
+#define mi_atomic_exchange_ptr_acq_rel(tp,p,x)          (tp*)mi_atomic_exchange_acq_rel((_Atomic(uintptr_t)*)(p),(uintptr_t)x)
+
+#define mi_atomic_loadi64_acquire(p)    mi_atomic(loadi64_explicit)(p,mi_memory_order(acquire))
+#define mi_atomic_loadi64_relaxed(p)    mi_atomic(loadi64_explicit)(p,mi_memory_order(relaxed))
+#define mi_atomic_storei64_release(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(release))
+#define mi_atomic_storei64_relaxed(p,x) mi_atomic(storei64_explicit)(p,x,mi_memory_order(relaxed))
+
 
-#else
-#ifdef __cplusplus
-#define  MI_USING_STD   using namespace std;
-#else
-#define  MI_USING_STD
 #endif
-static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add) {
-  MI_USING_STD
-  return atomic_fetch_add_explicit(p, add, memory_order_relaxed);
-}
-static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
-  MI_USING_STD
-  return atomic_fetch_and_explicit(p, x, memory_order_acq_rel);
-}
-static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
-  MI_USING_STD
-  return atomic_fetch_or_explicit(p, x, memory_order_acq_rel);
+
+
+// Atomically add a signed value; returns the previous value.
+static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add) {
+  return (intptr_t)mi_atomic_add_acq_rel((_Atomic(uintptr_t)*)p, (uintptr_t)add);
 }
-static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
-  MI_USING_STD
-  return atomic_compare_exchange_weak_explicit(p, &expected, desired, memory_order_acq_rel, memory_order_acquire);
+
+// Atomically subtract a signed value; returns the previous value.
+static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) {
+  return (intptr_t)mi_atomic_addi(p, -sub);
 }
-static inline bool mi_atomic_cas_strong(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
-  MI_USING_STD
-  return atomic_compare_exchange_strong_explicit(p, &expected, desired, memory_order_acq_rel, memory_order_acquire);
+
+// Yield 
+#if defined(__cplusplus)
+#include <thread>
+static inline void mi_atomic_yield(void) {
+  std::this_thread::yield();
 }
-static inline uintptr_t mi_atomic_exchange(volatile _Atomic(uintptr_t)* p, uintptr_t exchange) {
-  MI_USING_STD
-  return atomic_exchange_explicit(p, exchange, memory_order_acq_rel);
+#elif defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+static inline void mi_atomic_yield(void) {
+  YieldProcessor();
 }
-static inline uintptr_t mi_atomic_read_relaxed(const volatile _Atomic(uintptr_t)* p) {
-  MI_USING_STD
-  return atomic_load_explicit((volatile _Atomic(uintptr_t)*) p, memory_order_relaxed);
+#elif defined(__SSE2__)
+#include <emmintrin.h>
+static inline void mi_atomic_yield(void) {
+  _mm_pause();
 }
-static inline uintptr_t mi_atomic_read(const volatile _Atomic(uintptr_t)* p) {
-  MI_USING_STD
-  return atomic_load_explicit((volatile _Atomic(uintptr_t)*) p, memory_order_acquire);
+#elif (defined(__GNUC__) || defined(__clang__)) && \
+      (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__armel__) || defined(__ARMEL__) || \
+       defined(__aarch64__) || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__))
+#if defined(__x86_64__) || defined(__i386__)
+static inline void mi_atomic_yield(void) {
+  __asm__ volatile ("pause" ::: "memory");
 }
-static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
-  MI_USING_STD
-  return atomic_store_explicit(p, x, memory_order_release);
+#elif defined(__aarch64__)
+static inline void mi_atomic_yield(void) {
+  __asm__ volatile("wfe");
 }
-static inline void mi_atomic_addi64(volatile int64_t* p, int64_t add) {
-  MI_USING_STD
-  atomic_fetch_add_explicit((volatile _Atomic(int64_t)*)p, add, memory_order_relaxed);
+#elif (defined(__arm__) && __ARM_ARCH__ >= 7)
+static inline void mi_atomic_yield(void) {
+  __asm__ volatile("yield" ::: "memory");
 }
-static inline int64_t mi_atomic_readi64(volatile int64_t* p) {
-  MI_USING_STD
-  return atomic_load_explicit((volatile _Atomic(int64_t)*) p, memory_order_relaxed);
+#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
+static inline void mi_atomic_yield(void) {
+  __asm__ __volatile__ ("or 27,27,27" ::: "memory");
 }
-static inline void mi_atomic_maxi64(volatile int64_t* p, int64_t x) {
-  MI_USING_STD
-  int64_t current;
-  do {
-    current = mi_atomic_readi64(p);
-  } while (current < x && !atomic_compare_exchange_weak_explicit((volatile _Atomic(int64_t)*)p, &current, x, memory_order_acq_rel, memory_order_relaxed));
+#elif defined(__armel__) || defined(__ARMEL__)
+static inline void mi_atomic_yield(void) {
+  __asm__ volatile ("nop" ::: "memory");
 }
-
-#if defined(__cplusplus)
-  #include <thread>
-  static inline void mi_atomic_yield(void) {
-    std::this_thread::yield();
-  }
-#elif (defined(__GNUC__) || defined(__clang__)) && \
-      (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))
-#if defined(__x86_64__) || defined(__i386__)
-  static inline void mi_atomic_yield(void) {
-    asm volatile ("pause" ::: "memory");
-  }
-#elif defined(__arm__) || defined(__aarch64__)
-  static inline void mi_atomic_yield(void) {
-    asm volatile("yield");
-  }
 #endif
+#elif defined(__sun)
+// Fallback for other archs
+#include <synch.h>
+static inline void mi_atomic_yield(void) {
+  smt_pause();
+}
 #elif defined(__wasi__)
-  #include <sched.h>
-  static inline void mi_atomic_yield(void) {
-    sched_yield();
-  }
+#include <sched.h>
+static inline void mi_atomic_yield(void) {
+  sched_yield();
+}
 #else
-  #include <unistd.h>
-  static inline void mi_atomic_yield(void) {
-    sleep(0);
-  }
+#include <unistd.h>
+static inline void mi_atomic_yield(void) {
+  sleep(0);
+}
 #endif
 
-#endif
 
 #endif // __MIMALLOC_ATOMIC_H
index 2dc7e36a9aeadcdeb05d7f411821cf7e79706d97..d691eca5862450cd91842657806492584f6eb1e7 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -19,10 +19,11 @@ terms of the MIT license. A copy of the license can be found in the file
 #define MI_CACHE_LINE          64
 #if defined(_MSC_VER)
 #pragma warning(disable:4127)   // suppress constant conditional warning (due to MI_SECURE paths)
+#pragma warning(disable:26812)  // unscoped enum warning
 #define mi_decl_noinline        __declspec(noinline)
 #define mi_decl_thread          __declspec(thread)
 #define mi_decl_cache_align     __declspec(align(MI_CACHE_LINE))
-#elif (defined(__GNUC__) && (__GNUC__>=3))  // includes clang and icc
+#elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) // includes clang and icc
 #define mi_decl_noinline        __attribute__((noinline))
 #define mi_decl_thread          __thread
 #define mi_decl_cache_align     __attribute__((aligned(MI_CACHE_LINE)))
@@ -32,6 +33,20 @@ terms of the MIT license. A copy of the license can be found in the file
 #define mi_decl_cache_align
 #endif
 
+#if defined(__EMSCRIPTEN__) && !defined(__wasi__)
+#define __wasi__
+#endif
+
+#if defined(__cplusplus)
+#define mi_decl_externc       extern "C"
+#else
+#define mi_decl_externc  
+#endif
+
+#if !defined(_WIN32) && !defined(__wasi__) 
+#define  MI_USE_PTHREADS
+#include <pthread.h>
+#endif
 
 // "options.c"
 void       _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message);
@@ -47,51 +62,62 @@ void       _mi_random_init(mi_random_ctx_t* ctx);
 void       _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx);
 uintptr_t  _mi_random_next(mi_random_ctx_t* ctx);
 uintptr_t  _mi_heap_random_next(mi_heap_t* heap);
-uintptr_t  _os_random_weak(uintptr_t extra_seed);
+uintptr_t  _mi_os_random_weak(uintptr_t extra_seed);
 static inline uintptr_t _mi_random_shuffle(uintptr_t x);
 
 // init.c
-extern mi_stats_t       _mi_stats_main;
-extern const mi_page_t  _mi_page_empty;
+extern mi_decl_cache_align mi_stats_t       _mi_stats_main;
+extern mi_decl_cache_align const mi_page_t  _mi_page_empty;
 bool       _mi_is_main_thread(void);
-bool       _mi_preloading();  // true while the C runtime is not ready
+size_t     _mi_current_thread_count(void);
+bool       _mi_preloading(void);  // true while the C runtime is not ready
 
 // os.c
 size_t     _mi_os_page_size(void);
 void       _mi_os_init(void);                                      // called from process init
 void*      _mi_os_alloc(size_t size, mi_stats_t* stats);           // to allocate thread local data
 void       _mi_os_free(void* p, size_t size, mi_stats_t* stats);   // to free thread local data
-size_t     _mi_os_good_alloc_size(size_t size);
 
-// memory.c
-void*      _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld);
-void       _mi_mem_free(void* p, size_t size, size_t id, bool fully_committed, bool any_reset, mi_os_tld_t* tld);
+bool       _mi_os_protect(void* addr, size_t size);
+bool       _mi_os_unprotect(void* addr, size_t size);
+bool       _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* stats);
+bool       _mi_os_decommit(void* p, size_t size, mi_stats_t* stats);
+bool       _mi_os_reset(void* p, size_t size, mi_stats_t* stats);
+// bool       _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
+size_t     _mi_os_good_alloc_size(size_t size);
+bool       _mi_os_has_overcommit(void);
 
-bool       _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld);
-bool       _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
-bool       _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
-bool       _mi_mem_protect(void* addr, size_t size);
-bool       _mi_mem_unprotect(void* addr, size_t size);
+// arena.c
+void*      _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
+void*      _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
+void       _mi_arena_free(void* p, size_t size, size_t memid, bool is_committed, mi_os_tld_t* tld);
 
-void        _mi_mem_collect(mi_os_tld_t* tld);
+// "segment-cache.c"
+void*      _mi_segment_cache_pop(size_t size, mi_commit_mask_t* commit_mask, mi_commit_mask_t* decommit_mask, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
+bool       _mi_segment_cache_push(void* start, size_t size, size_t memid, const mi_commit_mask_t* commit_mask, const mi_commit_mask_t* decommit_mask, bool is_large, bool is_pinned, mi_os_tld_t* tld);
+void       _mi_segment_cache_collect(bool force, mi_os_tld_t* tld);
+void       _mi_segment_map_allocated_at(const mi_segment_t* segment);
+void       _mi_segment_map_freed_at(const mi_segment_t* segment);
 
 // "segment.c"
 mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld);
 void       _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld);
 void       _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld);
-uint8_t*   _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size); // page start for any page
+bool       _mi_segment_try_reclaim_abandoned( mi_heap_t* heap, bool try_all, mi_segments_tld_t* tld);
+void       _mi_segment_thread_collect(mi_segments_tld_t* tld);
 void       _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block);
 
-void       _mi_segment_thread_collect(mi_segments_tld_t* tld);
+uint8_t*   _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size); // page start for any page
 void       _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld);
 void       _mi_abandoned_await_readers(void);
+void       _mi_abandoned_collect(mi_heap_t* heap, bool force, mi_segments_tld_t* tld);
 
 
 
 // "page.c"
 void*      _mi_malloc_generic(mi_heap_t* heap, size_t size)  mi_attr_noexcept mi_attr_malloc;
 
-void       _mi_page_retire(mi_page_t* page);                                  // free the page if there are no other pages with many free blocks
+void       _mi_page_retire(mi_page_t* page) mi_attr_noexcept;                  // free the page if there are no other pages with many free blocks
 void       _mi_page_unfull(mi_page_t* page);
 void       _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force);   // free the page
 void       _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq);            // abandon the page, to be picked up by another thread...
@@ -107,7 +133,6 @@ void       _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page);   // callback fro
 
 size_t     _mi_bin_size(uint8_t bin);           // for stats
 uint8_t    _mi_bin(size_t size);                // for stats
-uint8_t    _mi_bsr(uintptr_t x);                // bit-scan-right, used on BSD in "os.c"
 
 // "heap.c"
 void       _mi_heap_destroy_pages(mi_heap_t* heap);
@@ -123,8 +148,8 @@ mi_msecs_t  _mi_clock_start(void);
 
 // "alloc.c"
 void*       _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept;  // called from `_mi_malloc_generic`
-void*       _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero);
-void*       _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero);
+void*       _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept;
+void*       _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept;
 mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p);
 bool        _mi_free_delayed_block(mi_block_t* block);
 void        _mi_block_zero_init(const mi_page_t* page, void* p, size_t size);
@@ -139,8 +164,8 @@ bool        _mi_page_is_valid(mi_page_t* page);
 // ------------------------------------------------------
 
 #if defined(__GNUC__) || defined(__clang__)
-#define mi_unlikely(x)     __builtin_expect((x),0)
-#define mi_likely(x)       __builtin_expect((x),1)
+#define mi_unlikely(x)     __builtin_expect(!!(x),false)
+#define mi_likely(x)       __builtin_expect(!!(x),true)
 #else
 #define mi_unlikely(x)     (x)
 #define mi_likely(x)       (x)
@@ -178,11 +203,11 @@ bool        _mi_page_is_valid(mi_page_t* page);
 /* -----------------------------------------------------------
   Inlined definitions
 ----------------------------------------------------------- */
-#define UNUSED(x)     (void)(x)
+#define MI_UNUSED(x)     (void)(x)
 #if (MI_DEBUG>0)
-#define UNUSED_RELEASE(x)
+#define MI_UNUSED_RELEASE(x)
 #else
-#define UNUSED_RELEASE(x)  UNUSED(x)
+#define MI_UNUSED_RELEASE(x)  MI_UNUSED(x)
 #endif
 
 #define MI_INIT4(x)   x(),x(),x(),x()
@@ -211,6 +236,18 @@ static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
   }
 }
 
+// Align downwards
+static inline uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) {
+  mi_assert_internal(alignment != 0);
+  uintptr_t mask = alignment - 1;
+  if ((alignment & mask) == 0) { // power of two?
+    return (sz & ~mask);
+  }
+  else {
+    return ((sz / alignment) * alignment);
+  }
+}
+
 // Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
 static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) {
   mi_assert_internal(divider != 0);
@@ -225,6 +262,7 @@ static inline bool mi_mem_is_zero(void* p, size_t size) {
   return true;
 }
 
+
 // Align a byte size to a size in _machine words_,
 // i.e. byte size == `wsize*sizeof(void*)`.
 static inline size_t _mi_wsize_from_size(size_t size) {
@@ -232,24 +270,19 @@ static inline size_t _mi_wsize_from_size(size_t size) {
   return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
 }
 
-// Does malloc satisfy the alignment constraints already?
-static inline bool mi_malloc_satisfies_alignment(size_t alignment, size_t size) {
-  return (alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2)));
-}
-
 // Overflow detecting multiply
-#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
+#if __has_builtin(__builtin_umul_overflow) || (defined(__GNUC__) && (__GNUC__ >= 5))
 #include <limits.h>      // UINT_MAX, ULONG_MAX
 #if defined(_CLOCK_T)    // for Illumos
 #undef _CLOCK_T
 #endif
 static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
-  #if (SIZE_MAX == UINT_MAX)
-    return __builtin_umul_overflow(count, size, total);
-  #elif (SIZE_MAX == ULONG_MAX)
-    return __builtin_umull_overflow(count, size, total);
+  #if (SIZE_MAX == ULONG_MAX)
+    return __builtin_umull_overflow(count, size, (unsigned long *)total);
+  #elif (SIZE_MAX == UINT_MAX)
+    return __builtin_umul_overflow(count, size, (unsigned int *)total);
   #else
-    return __builtin_umulll_overflow(count, size, total);
+    return __builtin_umulll_overflow(count, size, (unsigned long long *)total);
   #endif
 }
 #else /* __builtin_umul_overflow is unavailable */
@@ -287,7 +320,7 @@ We try to circumvent this in an efficient way:
 - macOSX : we use an unused TLS slot from the OS allocated slots (MI_TLS_SLOT). On OSX, the
            loader itself calls `malloc` even before the modules are initialized.
 - OpenBSD: we use an unused slot from the pthread block (MI_TLS_PTHREAD_SLOT_OFS).
-- DragonFly: not yet working.
+- DragonFly: defaults are working but seem slow compared to freeBSD (see PR #323)
 ------------------------------------------------------------------------------------------- */
 
 extern const mi_heap_t _mi_heap_empty;  // read-only empty heap, initial value of the thread local default heap
@@ -295,45 +328,57 @@ extern bool _mi_process_is_initialized;
 mi_heap_t*  _mi_heap_main_get(void);    // statically allocated main backing heap
 
 #if defined(MI_MALLOC_OVERRIDE)
-#if defined(__MACH__) // OSX
+#if defined(__APPLE__) // macOS
 #define MI_TLS_SLOT               89  // seems unused? 
+// #define MI_TLS_RECURSE_GUARD 1     
 // other possible unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89)
 // see <https://github.com/rweichler/substrate/blob/master/include/pthread_machdep.h>
 #elif defined(__OpenBSD__)
 // use end bytes of a name; goes wrong if anyone uses names > 23 characters (ptrhread specifies 16) 
 // see <https://github.com/openbsd/src/blob/master/lib/libc/include/thread_private.h#L371>
 #define MI_TLS_PTHREAD_SLOT_OFS   (6*sizeof(int) + 4*sizeof(void*) + 24)  
-#elif defined(__DragonFly__)
-#warning "mimalloc is not working correctly on DragonFly yet."
-#define MI_TLS_PTHREAD_SLOT_OFS   (4 + 1*sizeof(void*))  // offset `uniqueid` (also used by gdb?) <https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/lib/libthread_xu/thread/thr_private.h#L458>
+// #elif defined(__DragonFly__)
+// #warning "mimalloc is not working correctly on DragonFly yet."
+// #define MI_TLS_PTHREAD_SLOT_OFS   (4 + 1*sizeof(void*))  // offset `uniqueid` (also used by gdb?) <https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/lib/libthread_xu/thread/thr_private.h#L458>
+#elif defined(__ANDROID__)
+// See issue #381
+#define MI_TLS_PTHREAD
 #endif
 #endif
 
 #if defined(MI_TLS_SLOT)
 static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept;   // forward declaration
 #elif defined(MI_TLS_PTHREAD_SLOT_OFS)
-#include <pthread.h>
 static inline mi_heap_t** mi_tls_pthread_heap_slot(void) {
   pthread_t self = pthread_self();
   #if defined(__DragonFly__)
   if (self==NULL) {
-    static mi_heap_t* pheap_main = _mi_heap_main_get();
+    mi_heap_t* pheap_main = _mi_heap_main_get();
     return &pheap_main;
   }
   #endif
   return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS);
 }
 #elif defined(MI_TLS_PTHREAD)
-#include <pthread.h>
 extern pthread_key_t _mi_heap_default_key;
-#else
-extern mi_decl_thread mi_heap_t* _mi_heap_default;  // default heap to allocate from
 #endif
 
+// Default heap to allocate from (if not using TLS- or pthread slots).
+// Do not use this directly but use through `mi_heap_get_default()` (or the unchecked `mi_get_default_heap`).
+// This thread local variable is only used when neither MI_TLS_SLOT, MI_TLS_PTHREAD, or MI_TLS_PTHREAD_SLOT_OFS are defined.
+// However, on the Apple M1 we do use the address of this variable as the unique thread-id (issue #356).
+extern mi_decl_thread mi_heap_t* _mi_heap_default;  // default heap to allocate from
+
 static inline mi_heap_t* mi_get_default_heap(void) {
 #if defined(MI_TLS_SLOT)
   mi_heap_t* heap = (mi_heap_t*)mi_tls_slot(MI_TLS_SLOT);
-  return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
+  if (mi_unlikely(heap == NULL)) {
+    #ifdef __GNUC__
+    __asm(""); // prevent conditional load of the address of _mi_heap_empty
+    #endif
+    heap = (mi_heap_t*)&_mi_heap_empty;    
+  }
+  return heap;
 #elif defined(MI_TLS_PTHREAD_SLOT_OFS)
   mi_heap_t* heap = *mi_tls_pthread_heap_slot();
   return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
@@ -341,7 +386,7 @@ static inline mi_heap_t* mi_get_default_heap(void) {
   mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? _mi_heap_main_get() : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key));
   return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
 #else
-  #if defined(MI_TLS_RECURSE_GUARD)
+  #if defined(MI_TLS_RECURSE_GUARD)  
   if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get();
   #endif
   return _mi_heap_default;
@@ -389,35 +434,47 @@ static inline mi_segment_t* _mi_ptr_segment(const void* p) {
   return (mi_segment_t*)((uintptr_t)p & ~MI_SEGMENT_MASK);
 }
 
+static inline mi_page_t* mi_slice_to_page(mi_slice_t* s) {
+  mi_assert_internal(s->slice_offset== 0 && s->slice_count > 0);
+  return (mi_page_t*)(s);
+}
+
+static inline mi_slice_t* mi_page_to_slice(mi_page_t* p) {
+  mi_assert_internal(p->slice_offset== 0 && p->slice_count > 0);
+  return (mi_slice_t*)(p);
+}
+
 // Segment belonging to a page
 static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) {
-  mi_segment_t* segment = _mi_ptr_segment(page);
-  mi_assert_internal(segment == NULL || page == &segment->pages[page->segment_idx]);
+  mi_segment_t* segment = _mi_ptr_segment(page); 
+  mi_assert_internal(segment == NULL || ((mi_slice_t*)page >= segment->slices && (mi_slice_t*)page < segment->slices + segment->slice_entries));
   return segment;
 }
 
-// used internally
-static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) {
-  // if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0];  // huge pages
-  ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment;
-  mi_assert_internal(diff >= 0 && (size_t)diff < MI_SEGMENT_SIZE);
-  uintptr_t idx = (uintptr_t)diff >> segment->page_shift;
-  mi_assert_internal(idx < segment->capacity);
-  mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0);
-  return idx;
+static inline mi_slice_t* mi_slice_first(const mi_slice_t* slice) {
+  mi_slice_t* start = (mi_slice_t*)((uint8_t*)slice - slice->slice_offset);
+  mi_assert_internal(start >= _mi_ptr_segment(slice)->slices);
+  mi_assert_internal(start->slice_offset == 0);
+  mi_assert_internal(start + start->slice_count > slice);
+  return start;
 }
 
 // Get the page containing the pointer
 static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) {
-  uintptr_t idx = _mi_segment_page_idx_of(segment, p);
-  return &((mi_segment_t*)segment)->pages[idx];
+  ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment;
+  mi_assert_internal(diff >= 0 && diff < (ptrdiff_t)MI_SEGMENT_SIZE);
+  size_t idx = (size_t)diff >> MI_SEGMENT_SLICE_SHIFT;
+  mi_assert_internal(idx < segment->slice_entries);
+  mi_slice_t* slice0 = (mi_slice_t*)&segment->slices[idx];
+  mi_slice_t* slice = mi_slice_first(slice0);  // adjust to the block that holds the page data
+  mi_assert_internal(slice->slice_offset == 0);
+  mi_assert_internal(slice >= segment->slices && slice < segment->slices + segment->slice_entries);
+  return mi_slice_to_page(slice);
 }
 
 // Quick page start for initialized pages
 static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) {
-  const size_t bsize = page->xblock_size;
-  mi_assert_internal(bsize > 0 && (bsize%sizeof(void*)) == 0);
-  return _mi_segment_page_start(segment, page, bsize, page_size, NULL);
+  return _mi_segment_page_start(segment, page, page_size);
 }
 
 // Get the page containing the pointer
@@ -425,7 +482,7 @@ static inline mi_page_t* _mi_ptr_page(void* p) {
   return _mi_segment_page_of(_mi_ptr_segment(p), p);
 }
 
-// Get the block size of a page (special cased for huge objects)
+// Get the block size of a page (special case for huge objects)
 static inline size_t mi_page_block_size(const mi_page_t* page) {
   const size_t bsize = page->xblock_size;
   mi_assert_internal(bsize > 0);
@@ -434,7 +491,7 @@ static inline size_t mi_page_block_size(const mi_page_t* page) {
   }
   else {
     size_t psize;
-    _mi_segment_page_start(_mi_page_segment(page), page, bsize, &psize, NULL);
+    _mi_segment_page_start(_mi_page_segment(page), page, &psize);
     return psize;
   }
 }
@@ -445,24 +502,32 @@ static inline size_t mi_page_usable_block_size(const mi_page_t* page) {
   return mi_page_block_size(page) - MI_PADDING_SIZE;
 }
 
+// size of a segment
+static inline size_t mi_segment_size(mi_segment_t* segment) {
+  return segment->segment_slices * MI_SEGMENT_SLICE_SIZE;
+}
+
+static inline uint8_t* mi_segment_end(mi_segment_t* segment) {
+  return (uint8_t*)segment + mi_segment_size(segment);
+}
 
 // Thread free access
 static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) {
-  return (mi_block_t*)(mi_atomic_read_relaxed(&page->xthread_free) & ~3);
+  return (mi_block_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & ~3);
 }
 
 static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) {
-  return (mi_delayed_t)(mi_atomic_read_relaxed(&page->xthread_free) & 3);
+  return (mi_delayed_t)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & 3);
 }
 
 // Heap access
 static inline mi_heap_t* mi_page_heap(const mi_page_t* page) {
-  return (mi_heap_t*)(mi_atomic_read_relaxed(&page->xheap));
+  return (mi_heap_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xheap));
 }
 
 static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) {
   mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING);
-  mi_atomic_write(&page->xheap,(uintptr_t)heap);
+  mi_atomic_store_release(&page->xheap,(uintptr_t)heap);
 }
 
 // Thread free flag helpers
@@ -564,12 +629,13 @@ static inline bool mi_is_in_same_segment(const void* p, const void* q) {
 }
 
 static inline bool mi_is_in_same_page(const void* p, const void* q) {
-  mi_segment_t* segmentp = _mi_ptr_segment(p);
-  mi_segment_t* segmentq = _mi_ptr_segment(q);
-  if (segmentp != segmentq) return false;
-  uintptr_t idxp = _mi_segment_page_idx_of(segmentp, p);
-  uintptr_t idxq = _mi_segment_page_idx_of(segmentq, q);
-  return (idxp == idxq);
+  mi_segment_t* segment = _mi_ptr_segment(p);
+  if (_mi_ptr_segment(q) != segment) return false;
+  // assume q may be invalid // return (_mi_segment_page_of(segment, p) == _mi_segment_page_of(segment, q));
+  mi_page_t* page = _mi_segment_page_of(segment, p);
+  size_t psize;
+  uint8_t* start = _mi_segment_page_start(segment, page, &psize);
+  return (start <= (uint8_t*)q && (uint8_t*)q < start + psize);
 }
 
 static inline uintptr_t mi_rotl(uintptr_t x, uintptr_t shift) {
@@ -595,7 +661,7 @@ static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* bl
   #ifdef MI_ENCODE_FREELIST
   return (mi_block_t*)mi_ptr_decode(null, block->next, keys);
   #else
-  UNUSED(keys); UNUSED(null);
+  MI_UNUSED(keys); MI_UNUSED(null);
   return (mi_block_t*)block->next;
   #endif
 }
@@ -604,7 +670,7 @@ static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const
   #ifdef MI_ENCODE_FREELIST
   block->next = mi_ptr_encode(null, next, keys);
   #else
-  UNUSED(keys); UNUSED(null);
+  MI_UNUSED(keys); MI_UNUSED(null);
   block->next = (mi_encoded_t)next;
   #endif
 }
@@ -620,7 +686,7 @@ static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t*
   }
   return next;
   #else
-  UNUSED(page);
+  MI_UNUSED(page);
   return mi_block_nextx(page,block,NULL);
   #endif
 }
@@ -629,11 +695,57 @@ static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, c
   #ifdef MI_ENCODE_FREELIST
   mi_block_set_nextx(page,block,next, page->keys);
   #else
-  UNUSED(page);
+  MI_UNUSED(page);
   mi_block_set_nextx(page,block,next,NULL);
   #endif
 }
 
+
+// -------------------------------------------------------------------
+// commit mask
+// -------------------------------------------------------------------
+
+static inline void mi_commit_mask_create_empty(mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    cm->mask[i] = 0;
+  }
+}
+
+static inline void mi_commit_mask_create_full(mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    cm->mask[i] = ~((size_t)0);
+  }
+}
+
+static inline bool mi_commit_mask_is_empty(const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    if (cm->mask[i] != 0) return false;
+  }
+  return true;
+}
+
+static inline bool mi_commit_mask_is_full(const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    if (cm->mask[i] != ~((size_t)0)) return false;
+  }
+  return true;
+}
+
+// defined in `segment.c`:
+size_t _mi_commit_mask_committed_size(const mi_commit_mask_t* cm, size_t total);
+size_t _mi_commit_mask_next_run(const mi_commit_mask_t* cm, size_t* idx);
+
+#define mi_commit_mask_foreach(cm,idx,count) \
+  idx = 0; \
+  while ((count = _mi_commit_mask_next_run(cm,&idx)) > 0) { 
+        
+#define mi_commit_mask_foreach_end() \
+    idx += count; \
+  }
+      
+
+
+
 // -------------------------------------------------------------------
 // Fast "random" shuffle
 // -------------------------------------------------------------------
@@ -665,13 +777,14 @@ static inline uintptr_t _mi_random_shuffle(uintptr_t x) {
 int    _mi_os_numa_node_get(mi_os_tld_t* tld);
 size_t _mi_os_numa_node_count_get(void);
 
-extern size_t _mi_numa_node_count;
+extern _Atomic(size_t) _mi_numa_node_count;
 static inline int _mi_os_numa_node(mi_os_tld_t* tld) {
-  if (mi_likely(_mi_numa_node_count == 1)) return 0;
+  if (mi_likely(mi_atomic_load_relaxed(&_mi_numa_node_count) == 1)) return 0;
   else return _mi_os_numa_node_get(tld);
 }
 static inline size_t _mi_os_numa_node_count(void) {
-  if (mi_likely(_mi_numa_node_count>0)) return _mi_numa_node_count;
+  const size_t count = mi_atomic_load_relaxed(&_mi_numa_node_count);
+  if (mi_likely(count>0)) return count;
   else return _mi_os_numa_node_count_get();
 }
 
@@ -679,69 +792,257 @@ static inline size_t _mi_os_numa_node_count(void) {
 // -------------------------------------------------------------------
 // Getting the thread id should be performant as it is called in the
 // fast path of `_mi_free` and we specialize for various platforms.
+// We only require _mi_threadid() to return a unique id for each thread.
 // -------------------------------------------------------------------
 #if defined(_WIN32)
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
+static inline mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
   // Windows: works on Intel and ARM in both 32- and 64-bit
   return (uintptr_t)NtCurrentTeb();
 }
 
-#elif defined(__GNUC__) && \
-      (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))
+// We use assembly for a fast thread id on the main platforms. The TLS layout depends on 
+// both the OS and libc implementation so we use specific tests for each main platform.
+// If you test on another platform and it works please send a PR :-)
+// see also https://akkadia.org/drepper/tls.pdf for more info on the TLS register.
+#elif defined(__GNUC__) && ( \
+           (defined(__GLIBC__)   && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \
+        || (defined(__APPLE__)   && (defined(__x86_64__) || defined(__aarch64__))) \
+        || (defined(__BIONIC__)  && (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))) \
+        || (defined(__FreeBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \
+        || (defined(__OpenBSD__) && (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))) \
+      )
 
-// TLS register on x86 is in the FS or GS register, see: https://akkadia.org/drepper/tls.pdf
 static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept {
   void* res;
   const size_t ofs = (slot*sizeof(void*));
-#if defined(__i386__)
-  __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // 32-bit always uses GS
-#elif defined(__MACH__) && defined(__x86_64__)
-  __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x86_64 macOSX uses GS
-#elif defined(__x86_64__)
-  __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x86_64 Linux, BSD uses FS
-#elif defined(__arm__)
-  void** tcb; UNUSED(ofs);
-  asm volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
-  res = tcb[slot];
-#elif defined(__aarch64__)
-  void** tcb; UNUSED(ofs);
-  asm volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
-  res = tcb[slot];
-#endif
+  #if defined(__i386__)
+    __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x86 32-bit always uses GS
+  #elif defined(__APPLE__) && defined(__x86_64__)
+    __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x86_64 macOSX uses GS
+  #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
+    __asm__("movl %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x32 ABI
+  #elif defined(__x86_64__)
+    __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : );  // x86_64 Linux, BSD uses FS
+  #elif defined(__arm__)
+    void** tcb; MI_UNUSED(ofs);
+    __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
+    res = tcb[slot];
+  #elif defined(__aarch64__)
+    void** tcb; MI_UNUSED(ofs);
+    #if defined(__APPLE__) // M1, issue #343
+    __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+    #else
+    __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+    #endif
+    res = tcb[slot];
+  #endif
   return res;
 }
 
-// setting is only used on macOSX for now
+// setting a tls slot is only used on macOS for now
 static inline void mi_tls_slot_set(size_t slot, void* value) mi_attr_noexcept {
   const size_t ofs = (slot*sizeof(void*));
-#if defined(__i386__)
-  __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // 32-bit always uses GS
-#elif defined(__MACH__) && defined(__x86_64__)
-  __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // x86_64 macOSX uses GS
-#elif defined(__x86_64__)
-  __asm__("movq %1,%%fs:%1" : "=m" (*((void**)ofs)) : "rn" (value) : );  // x86_64 Linux, BSD uses FS
-#elif defined(__arm__)
-  void** tcb; UNUSED(ofs);
-  asm volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
-  tcb[slot] = value;
-#elif defined(__aarch64__)
-  void** tcb; UNUSED(ofs);
-  asm volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
-  tcb[slot] = value;
-#endif
+  #if defined(__i386__)
+    __asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // 32-bit always uses GS
+  #elif defined(__APPLE__) && defined(__x86_64__)
+    __asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // x86_64 macOS uses GS
+  #elif defined(__x86_64__) && (MI_INTPTR_SIZE==4)
+    __asm__("movl %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // x32 ABI
+  #elif defined(__x86_64__)
+    __asm__("movq %1,%%fs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : );  // x86_64 Linux, BSD uses FS
+  #elif defined(__arm__)
+    void** tcb; MI_UNUSED(ofs);
+    __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
+    tcb[slot] = value;
+  #elif defined(__aarch64__)
+    void** tcb; MI_UNUSED(ofs);
+    #if defined(__APPLE__) // M1, issue #343
+    __asm__ volatile ("mrs %0, tpidrro_el0\nbic %0, %0, #7" : "=r" (tcb));
+    #else
+    __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
+    #endif
+    tcb[slot] = value;
+  #endif
 }
 
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
-  // in all our targets, slot 0 is the pointer to the thread control block
-  return (uintptr_t)mi_tls_slot(0);
+static inline mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
+  #if defined(__BIONIC__)
+    // issue #384, #495: on the Bionic libc (Android), slot 1 is the thread id
+    // see: https://github.com/aosp-mirror/platform_bionic/blob/c44b1d0676ded732df4b3b21c5f798eacae93228/libc/platform/bionic/tls_defines.h#L86
+    return (uintptr_t)mi_tls_slot(1);
+  #else
+    // in all our other targets, slot 0 is the thread id
+    // glibc: https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/x86_64/nptl/tls.h
+    // apple: https://github.com/apple/darwin-xnu/blob/main/libsyscall/os/tsd.h#L36
+    return (uintptr_t)mi_tls_slot(0);
+  #endif
 }
+
 #else
-// otherwise use standard C
-static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
+
+// otherwise use portable C, taking the address of a thread local variable (this is still very fast on most platforms).
+static inline mi_threadid_t _mi_thread_id(void) mi_attr_noexcept {
   return (uintptr_t)&_mi_heap_default;
 }
+
+#endif
+
+
+// -----------------------------------------------------------------------
+// Count bits: trailing or leading zeros (with MI_INTPTR_BITS on all zero)
+// -----------------------------------------------------------------------
+
+#if defined(__GNUC__)
+
+#include <limits.h>       // LONG_MAX
+#define MI_HAVE_FAST_BITSCAN
+static inline size_t mi_clz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;
+#if (INTPTR_MAX == LONG_MAX)
+  return __builtin_clzl(x);
+#else
+  return __builtin_clzll(x);
+#endif
+}
+static inline size_t mi_ctz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;
+#if (INTPTR_MAX == LONG_MAX)
+  return __builtin_ctzl(x);
+#else
+  return __builtin_ctzll(x);
+#endif
+}
+
+#elif defined(_MSC_VER) 
+
+#include <limits.h>       // LONG_MAX
+#define MI_HAVE_FAST_BITSCAN
+static inline size_t mi_clz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;
+  unsigned long idx;
+#if (INTPTR_MAX == LONG_MAX)
+  _BitScanReverse(&idx, x);
+#else
+  _BitScanReverse64(&idx, x);
+#endif  
+  return ((MI_INTPTR_BITS - 1) - idx);
+}
+static inline size_t mi_ctz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;
+  unsigned long idx;
+#if (INTPTR_MAX == LONG_MAX)
+  _BitScanForward(&idx, x);
+#else
+  _BitScanForward64(&idx, x);
+#endif  
+  return idx;
+}
+
+#else
+static inline size_t mi_ctz32(uint32_t x) {
+  // de Bruijn multiplication, see <http://supertech.csail.mit.edu/papers/debruijn.pdf>
+  static const unsigned char debruijn[32] = {
+    0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+    31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+  };
+  if (x==0) return 32;
+  return debruijn[((x & -(int32_t)x) * 0x077CB531UL) >> 27];
+}
+static inline size_t mi_clz32(uint32_t x) {
+  // de Bruijn multiplication, see <http://supertech.csail.mit.edu/papers/debruijn.pdf>
+  static const uint8_t debruijn[32] = {
+    31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
+    23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
+  };
+  if (x==0) return 32;
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  return debruijn[(uint32_t)(x * 0x07C4ACDDUL) >> 27];
+}
+
+static inline size_t mi_clz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;  
+#if (MI_INTPTR_BITS <= 32)
+  return mi_clz32((uint32_t)x);
+#else
+  size_t count = mi_clz32((uint32_t)(x >> 32));
+  if (count < 32) return count;
+  return (32 + mi_clz32((uint32_t)x));
+#endif
+}
+static inline size_t mi_ctz(uintptr_t x) {
+  if (x==0) return MI_INTPTR_BITS;
+#if (MI_INTPTR_BITS <= 32)
+  return mi_ctz32((uint32_t)x);
+#else
+  size_t count = mi_ctz32((uint32_t)x);
+  if (count < 32) return count;
+  return (32 + mi_ctz32((uint32_t)(x>>32)));
+#endif
+}
+
+#endif
+
+// "bit scan reverse": Return index of the highest bit (or MI_INTPTR_BITS if `x` is zero)
+static inline size_t mi_bsr(uintptr_t x) {
+  return (x==0 ? MI_INTPTR_BITS : MI_INTPTR_BITS - 1 - mi_clz(x));
+}
+
+
+// ---------------------------------------------------------------------------------
+// Provide our own `_mi_memcpy` for potential performance optimizations.
+//
+// For now, only on Windows with msvc/clang-cl we optimize to `rep movsb` if 
+// we happen to run on x86/x64 cpu's that have "fast short rep movsb" (FSRM) support 
+// (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017). See also issue #201 and pr #253. 
+// ---------------------------------------------------------------------------------
+
+#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))
+#include <intrin.h>
+#include <string.h>
+extern bool _mi_cpu_has_fsrm;
+static inline void _mi_memcpy(void* dst, const void* src, size_t n) {
+  if (_mi_cpu_has_fsrm) {
+    __movsb((unsigned char*)dst, (const unsigned char*)src, n);
+  }
+  else {
+    memcpy(dst, src, n); // todo: use noinline?
+  }
+}
+#else
+#include <string.h>
+static inline void _mi_memcpy(void* dst, const void* src, size_t n) {
+  memcpy(dst, src, n);
+}
+#endif
+
+
+// -------------------------------------------------------------------------------
+// The `_mi_memcpy_aligned` can be used if the pointers are machine-word aligned 
+// This is used for example in `mi_realloc`.
+// -------------------------------------------------------------------------------
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+// On GCC/CLang we provide a hint that the pointers are word aligned.
+#include <string.h>
+static inline void _mi_memcpy_aligned(void* dst, const void* src, size_t n) {
+  mi_assert_internal(((uintptr_t)dst % MI_INTPTR_SIZE == 0) && ((uintptr_t)src % MI_INTPTR_SIZE == 0));
+  void* adst = __builtin_assume_aligned(dst, MI_INTPTR_SIZE);
+  const void* asrc = __builtin_assume_aligned(src, MI_INTPTR_SIZE);
+  _mi_memcpy(adst, asrc, n);
+}
+#else
+// Default fallback on `_mi_memcpy`
+static inline void _mi_memcpy_aligned(void* dst, const void* src, size_t n) {
+  mi_assert_internal(((uintptr_t)dst % MI_INTPTR_SIZE == 0) && ((uintptr_t)src % MI_INTPTR_SIZE == 0));
+  _mi_memcpy(dst, src, n);
+}
 #endif
 
 
index fded0c04f83cd939389534b8658faf482b215651..2749a0be941c97f97d02c9b8a4c027d0427c2ef4 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018,2019 Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020 Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -25,6 +25,9 @@ terms of the MIT license. A copy of the license can be found in the file
   void operator delete(void* p) noexcept              { mi_free(p); };
   void operator delete[](void* p) noexcept            { mi_free(p); };
 
+  void operator delete  (void* p, const std::nothrow_t&) noexcept { mi_free(p); }
+  void operator delete[](void* p, const std::nothrow_t&) noexcept { mi_free(p); }
+
   void* operator new(std::size_t n) noexcept(false)   { return mi_new(n); }
   void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); }
 
@@ -41,9 +44,11 @@ terms of the MIT license. A copy of the license can be found in the file
   void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
   void operator delete  (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
   void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
-
-  void* operator new( std::size_t n, std::align_val_t al)   noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
-  void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
+  void operator delete  (void* p, std::align_val_t al, const std::nothrow_t& tag) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
+  void operator delete[](void* p, std::align_val_t al, const std::nothrow_t& tag) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
+  
+  void* operator new  (std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
+  void* operator new[](std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
   void* operator new  (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
   void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
   #endif
index 201fb8b49ba9b7291cad3ff2b09dc4498845cdad..c63b0b91a7c28322b608c1ef508320b110b25ed7 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018,2019 Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020 Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -24,7 +24,7 @@ not accidentally mix pointers from different allocators).
 #define free(p)                 mi_free(p)
 
 #define strdup(s)               mi_strdup(s)
-#define strndup(s)              mi_strndup(s)
+#define strndup(s,n)              mi_strndup(s,n)
 #define realpath(f,n)           mi_realpath(f,n)
 
 // Microsoft extensions
@@ -33,7 +33,7 @@ not accidentally mix pointers from different allocators).
 #define _recalloc(p,n,c)        mi_recalloc(p,n,c)
 
 #define _strdup(s)              mi_strdup(s)
-#define _strndup(s)             mi_strndup(s)
+#define _strndup(s,n)           mi_strndup(s,n)
 #define _wcsdup(s)              (wchar_t*)mi_wcsdup((const unsigned short*)(s))
 #define _mbsdup(s)              mi_mbsdup(s)
 #define _dupenv_s(b,n,v)        mi_dupenv_s(b,n,v)
@@ -48,6 +48,7 @@ not accidentally mix pointers from different allocators).
 #define valloc(n)               mi_valloc(n)
 #define pvalloc(n)              mi_pvalloc(n)
 #define reallocarray(p,s,n)     mi_reallocarray(p,s,n)
+#define reallocarr(p,s,n)       mi_reallocarr(p,s,n)
 #define memalign(a,n)           mi_memalign(a,n)
 #define aligned_alloc(a,n)      mi_aligned_alloc(a,n)
 #define posix_memalign(p,a,n)   mi_posix_memalign(p,a,n)
index 449e2e415d1c25f81e05965e144d66d76fc990af..fb75ea464c40e1ad2801a607a907678d40694e08 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -10,11 +10,17 @@ terms of the MIT license. A copy of the license can be found in the file
 
 #include <stddef.h>   // ptrdiff_t
 #include <stdint.h>   // uintptr_t, uint16_t, etc
-#include <mimalloc-atomic.h>  // _Atomic
+#include "mimalloc-atomic.h"  // _Atomic
+
+#ifdef _MSC_VER
+#pragma warning(disable:4214) // bitfield is not int
+#endif 
 
 // Minimal alignment necessary. On most platforms 16 bytes are needed
-// due to SSE registers for example. This must be at least `MI_INTPTR_SIZE`
+// due to SSE registers for example. This must be at least `sizeof(void*)`
+#ifndef MI_MAX_ALIGN_SIZE
 #define MI_MAX_ALIGN_SIZE  16   // sizeof(max_align_t)
+#endif
 
 // ------------------------------------------------------
 // Variants
@@ -61,6 +67,7 @@ terms of the MIT license. A copy of the license can be found in the file
 #define MI_ENCODE_FREELIST  1
 #endif
 
+
 // ------------------------------------------------------
 // Platform specific values
 // ------------------------------------------------------
@@ -77,20 +84,43 @@ terms of the MIT license. A copy of the license can be found in the file
 // or otherwise one might define an intptr_t type that is larger than a pointer...
 // ------------------------------------------------------
 
-#if INTPTR_MAX == 9223372036854775807LL
+#if INTPTR_MAX > INT64_MAX
+# define MI_INTPTR_SHIFT (4)  // assume 128-bit  (as on arm CHERI for example)
+#elif INTPTR_MAX == INT64_MAX
 # define MI_INTPTR_SHIFT (3)
-#elif INTPTR_MAX == 2147483647LL
+#elif INTPTR_MAX == INT32_MAX
 # define MI_INTPTR_SHIFT (2)
 #else
-#error platform must be 32 or 64 bits
+#error platform pointers must be 32, 64, or 128 bits
+#endif
+
+#if SIZE_MAX == UINT64_MAX
+# define MI_SIZE_SHIFT (3)
+typedef int64_t  mi_ssize_t;
+#elif SIZE_MAX == UINT32_MAX
+# define MI_SIZE_SHIFT (2)
+typedef int32_t  mi_ssize_t;
+#else
+#error platform objects must be 32 or 64 bits
+#endif
+
+#if (SIZE_MAX/2) > LONG_MAX
+# define MI_ZU(x)  x##ULL
+# define MI_ZI(x)  x##LL
+#else
+# define MI_ZU(x)  x##UL
+# define MI_ZI(x)  x##L
 #endif
 
 #define MI_INTPTR_SIZE  (1<<MI_INTPTR_SHIFT)
 #define MI_INTPTR_BITS  (MI_INTPTR_SIZE*8)
 
-#define KiB     ((size_t)1024)
-#define MiB     (KiB*KiB)
-#define GiB     (MiB*KiB)
+#define MI_SIZE_SIZE  (1<<MI_SIZE_SHIFT)
+#define MI_SIZE_BITS  (MI_SIZE_SIZE*8)
+
+#define MI_KiB     (MI_ZU(1024))
+#define MI_MiB     (MI_KiB*MI_KiB)
+#define MI_GiB     (MI_MiB*MI_KiB)
 
 
 // ------------------------------------------------------
@@ -98,45 +128,70 @@ terms of the MIT license. A copy of the license can be found in the file
 // ------------------------------------------------------
 
 // Main tuning parameters for segment and page sizes
-// Sizes for 64-bit, divide by two for 32-bit
-#define MI_SMALL_PAGE_SHIFT               (13 + MI_INTPTR_SHIFT)      // 64kb
-#define MI_MEDIUM_PAGE_SHIFT              ( 3 + MI_SMALL_PAGE_SHIFT)  // 512kb
-#define MI_LARGE_PAGE_SHIFT               ( 3 + MI_MEDIUM_PAGE_SHIFT) // 4mb
-#define MI_SEGMENT_SHIFT                  ( MI_LARGE_PAGE_SHIFT)      // 4mb
+// Sizes for 64-bit (usually divide by two for 32-bit)
+#define MI_SEGMENT_SLICE_SHIFT            (13 + MI_INTPTR_SHIFT)         // 64KiB  (32KiB on 32-bit)
+
+#if MI_INTPTR_SIZE > 4
+#define MI_SEGMENT_SHIFT                  (10 + MI_SEGMENT_SLICE_SHIFT)  // 64MiB
+#else
+#define MI_SEGMENT_SHIFT                  ( 7 + MI_SEGMENT_SLICE_SHIFT)  // 4MiB on 32-bit
+#endif
+
+#define MI_SMALL_PAGE_SHIFT               (MI_SEGMENT_SLICE_SHIFT)       // 64KiB
+#define MI_MEDIUM_PAGE_SHIFT              ( 3 + MI_SMALL_PAGE_SHIFT)     // 512KiB
+
 
 // Derived constants
-#define MI_SEGMENT_SIZE                   (1UL<<MI_SEGMENT_SHIFT)
-#define MI_SEGMENT_MASK                   ((uintptr_t)MI_SEGMENT_SIZE - 1)
-
-#define MI_SMALL_PAGE_SIZE                (1UL<<MI_SMALL_PAGE_SHIFT)
-#define MI_MEDIUM_PAGE_SIZE               (1UL<<MI_MEDIUM_PAGE_SHIFT)
-#define MI_LARGE_PAGE_SIZE                (1UL<<MI_LARGE_PAGE_SHIFT)
-
-#define MI_SMALL_PAGES_PER_SEGMENT        (MI_SEGMENT_SIZE/MI_SMALL_PAGE_SIZE)
-#define MI_MEDIUM_PAGES_PER_SEGMENT       (MI_SEGMENT_SIZE/MI_MEDIUM_PAGE_SIZE)
-#define MI_LARGE_PAGES_PER_SEGMENT        (MI_SEGMENT_SIZE/MI_LARGE_PAGE_SIZE)
-
-// The max object size are checked to not waste more than 12.5% internally over the page sizes.
-// (Except for large pages since huge objects are allocated in 4MiB chunks)
-#define MI_SMALL_OBJ_SIZE_MAX             (MI_SMALL_PAGE_SIZE/4)   // 16kb
-#define MI_MEDIUM_OBJ_SIZE_MAX            (MI_MEDIUM_PAGE_SIZE/4)  // 128kb
-#define MI_LARGE_OBJ_SIZE_MAX             (MI_LARGE_PAGE_SIZE/2)   // 2mb
+#define MI_SEGMENT_SIZE                   (MI_ZU(1)<<MI_SEGMENT_SHIFT)
+#define MI_SEGMENT_ALIGN                  MI_SEGMENT_SIZE
+#define MI_SEGMENT_MASK                   (MI_SEGMENT_SIZE - 1)
+#define MI_SEGMENT_SLICE_SIZE             (MI_ZU(1)<< MI_SEGMENT_SLICE_SHIFT)
+#define MI_SLICES_PER_SEGMENT             (MI_SEGMENT_SIZE / MI_SEGMENT_SLICE_SIZE) // 1024
+
+#define MI_SMALL_PAGE_SIZE                (MI_ZU(1)<<MI_SMALL_PAGE_SHIFT)
+#define MI_MEDIUM_PAGE_SIZE               (MI_ZU(1)<<MI_MEDIUM_PAGE_SHIFT)
+
+#define MI_SMALL_OBJ_SIZE_MAX             (MI_SMALL_PAGE_SIZE/4)   // 8KiB on 64-bit
+#define MI_MEDIUM_OBJ_SIZE_MAX            (MI_MEDIUM_PAGE_SIZE/4)  // 128KiB on 64-bit
+#define MI_MEDIUM_OBJ_WSIZE_MAX           (MI_MEDIUM_OBJ_SIZE_MAX/MI_INTPTR_SIZE)   
+#define MI_LARGE_OBJ_SIZE_MAX             (MI_SEGMENT_SIZE/2)      // 32MiB on 64-bit
 #define MI_LARGE_OBJ_WSIZE_MAX            (MI_LARGE_OBJ_SIZE_MAX/MI_INTPTR_SIZE)
-#define MI_HUGE_OBJ_SIZE_MAX              (2*MI_INTPTR_SIZE*MI_SEGMENT_SIZE)        // (must match MI_REGION_MAX_ALLOC_SIZE in memory.c)
 
 // Maximum number of size classes. (spaced exponentially in 12.5% increments)
 #define MI_BIN_HUGE  (73U)
 
-#if (MI_LARGE_OBJ_WSIZE_MAX >= 655360)
-#error "define more bins"
+#if (MI_MEDIUM_OBJ_WSIZE_MAX >= 655360)
+#error "mimalloc internal: define more bins"
+#endif
+#if (MI_ALIGNMENT_MAX > MI_SEGMENT_SIZE/2)
+#error "mimalloc internal: the max aligned boundary is too large for the segment size"
 #endif
+#if (MI_ALIGNED_MAX % MI_SEGMENT_SLICE_SIZE != 0)
+#error "mimalloc internal: the max aligned boundary must be an integral multiple of the segment slice size"
+#endif
+
+// Maximum slice offset (15)
+#define MI_MAX_SLICE_OFFSET               ((MI_ALIGNMENT_MAX / MI_SEGMENT_SLICE_SIZE) - 1)
 
 // Used as a special value to encode block sizes in 32 bits.
-#define MI_HUGE_BLOCK_SIZE   ((uint32_t)MI_HUGE_OBJ_SIZE_MAX)
+#define MI_HUGE_BLOCK_SIZE                ((uint32_t)(2*MI_GiB))
+
+// blocks up to this size are always allocated aligned
+#define MI_MAX_ALIGN_GUARANTEE            (8*MI_MAX_ALIGN_SIZE)  
+
+
+
+
+// ------------------------------------------------------
+// Mimalloc pages contain allocated blocks
+// ------------------------------------------------------
 
 // The free lists use encoded next fields
 // (Only actually encodes when MI_ENCODED_FREELIST is defined.)
-typedef uintptr_t mi_encoded_t;
+typedef uintptr_t  mi_encoded_t;
+
+// thread id's
+typedef size_t     mi_threadid_t;
 
 // free lists contain blocks
 typedef struct mi_block_s {
@@ -155,6 +210,7 @@ typedef enum mi_delayed_e {
 
 // The `in_full` and `has_aligned` page flags are put in a union to efficiently
 // test if both are false (`full_aligned == 0`) in the `mi_free` routine.
+#if !MI_TSAN
 typedef union mi_page_flags_s {
   uint8_t full_aligned;
   struct {
@@ -162,6 +218,16 @@ typedef union mi_page_flags_s {
     uint8_t has_aligned : 1;
   } x;
 } mi_page_flags_t;
+#else
+// under thread sanitizer, use a byte for each flag to suppress warning, issue #130
+typedef union mi_page_flags_s {
+  uint16_t full_aligned;
+  struct {
+    uint8_t in_full;
+    uint8_t has_aligned;
+  } x;
+} mi_page_flags_t;
+#endif
 
 // Thread free list.
 // We use the bottom 2 bits of the pointer for mi_delayed_t flags
@@ -201,18 +267,18 @@ typedef uintptr_t mi_thread_free_t;
 //   will be freed correctly even if only other threads free blocks.
 typedef struct mi_page_s {
   // "owned" by the segment
-  uint8_t               segment_idx;       // index in the segment `pages` array, `page == &segment->pages[page->segment_idx]`
-  uint8_t               segment_in_use:1;  // `true` if the segment allocated this page
-  uint8_t               is_reset:1;        // `true` if the page memory was reset
-  uint8_t               is_committed:1;    // `true` if the page virtual memory is committed
-  uint8_t               is_zero_init:1;    // `true` if the page was zero initialized
+  uint32_t              slice_count;       // slices in this page (0 if not a page)
+  uint32_t              slice_offset;      // distance from the actual page data slice (0 if a page)
+  uint8_t               is_reset : 1;        // `true` if the page memory was reset
+  uint8_t               is_committed : 1;    // `true` if the page virtual memory is committed
+  uint8_t               is_zero_init : 1;    // `true` if the page was zero initialized
 
   // layout like this to optimize access in `mi_malloc` and `mi_free`
   uint16_t              capacity;          // number of blocks committed, must be the first field, see `segment.c:page_clear`
   uint16_t              reserved;          // number of blocks reserved in memory
   mi_page_flags_t       flags;             // `in_full` and `has_aligned` flags (8 bits)
-  uint8_t               is_zero:1;         // `true` if the blocks in the free list are zero initialized
-  uint8_t               retire_expire:7;   // expiration count for retired blocks
+  uint8_t               is_zero : 1;         // `true` if the blocks in the free list are zero initialized
+  uint8_t               retire_expire : 7;   // expiration count for retired blocks
 
   mi_block_t*           free;              // list of available free blocks (`malloc` allocates from this list)
   #ifdef MI_ENCODE_FREELIST
@@ -221,50 +287,95 @@ typedef struct mi_page_s {
   uint32_t              used;              // number of blocks in use (including blocks in `local_free` and `thread_free`)
   uint32_t              xblock_size;       // size available in each block (always `>0`) 
 
-  mi_block_t*           local_free;        // list of deferred free blocks by this thread (migrates to `free`)
-  volatile _Atomic(mi_thread_free_t) xthread_free;   // list of deferred free blocks freed by other threads
-  volatile _Atomic(uintptr_t)        xheap;
-  
-  struct mi_page_s*     next;              // next page owned by this thread with the same `block_size`
-  struct mi_page_s*     prev;              // previous page owned by this thread with the same `block_size`
+  mi_block_t* local_free;                  // list of deferred free blocks by this thread (migrates to `free`)
+  _Atomic(mi_thread_free_t) xthread_free;  // list of deferred free blocks freed by other threads
+  _Atomic(uintptr_t)        xheap;
+
+  struct mi_page_s* next;                  // next page owned by this thread with the same `block_size`
+  struct mi_page_s* prev;                  // previous page owned by this thread with the same `block_size`
+
+  // 64-bit 9 words, 32-bit 12 words, (+2 for secure)
+  #if MI_INTPTR_SIZE==8
+  uintptr_t padding[1];
+  #endif
 } mi_page_t;
 
 
 
 typedef enum mi_page_kind_e {
-  MI_PAGE_SMALL,    // small blocks go into 64kb pages inside a segment
-  MI_PAGE_MEDIUM,   // medium blocks go into 512kb pages inside a segment
-  MI_PAGE_LARGE,    // larger blocks go into a single page spanning a whole segment
-  MI_PAGE_HUGE      // huge blocks (>512kb) are put into a single page in a segment of the exact size (but still 2mb aligned)
+  MI_PAGE_SMALL,    // small blocks go into 64KiB pages inside a segment
+  MI_PAGE_MEDIUM,   // medium blocks go into medium pages inside a segment
+  MI_PAGE_LARGE,    // larger blocks go into a page of just one block
+  MI_PAGE_HUGE,     // huge blocks (> 16 MiB) are put into a single page in a single segment.
 } mi_page_kind_t;
 
-// Segments are large allocated memory blocks (2mb on 64 bit) from
+typedef enum mi_segment_kind_e {
+  MI_SEGMENT_NORMAL, // MI_SEGMENT_SIZE size with pages inside.
+  MI_SEGMENT_HUGE,   // > MI_LARGE_SIZE_MAX segment with just one huge page inside.
+} mi_segment_kind_t;
+
+// ------------------------------------------------------
+// A segment holds a commit mask where a bit is set if
+// the corresponding MI_COMMIT_SIZE area is committed.
+// The MI_COMMIT_SIZE must be a multiple of the slice
+// size. If it is equal we have the most fine grained 
+// decommit (but setting it higher can be more efficient).
+// The MI_MINIMAL_COMMIT_SIZE is the minimal amount that will
+// be committed in one go which can be set higher than
+// MI_COMMIT_SIZE for efficiency (while the decommit mask
+// is still tracked in fine-grained MI_COMMIT_SIZE chunks)
+// ------------------------------------------------------
+
+#define MI_MINIMAL_COMMIT_SIZE      (2*MI_MiB)
+#define MI_COMMIT_SIZE              (MI_SEGMENT_SLICE_SIZE)              // 64KiB
+#define MI_COMMIT_MASK_BITS         (MI_SEGMENT_SIZE / MI_COMMIT_SIZE)  
+#define MI_COMMIT_MASK_FIELD_BITS    MI_SIZE_BITS
+#define MI_COMMIT_MASK_FIELD_COUNT  (MI_COMMIT_MASK_BITS / MI_COMMIT_MASK_FIELD_BITS)
+
+#if (MI_COMMIT_MASK_BITS != (MI_COMMIT_MASK_FIELD_COUNT * MI_COMMIT_MASK_FIELD_BITS))
+#error "the segment size must be exactly divisible by the (commit size * size_t bits)"
+#endif
+
+typedef struct mi_commit_mask_s {
+  size_t mask[MI_COMMIT_MASK_FIELD_COUNT];
+} mi_commit_mask_t;
+
+typedef mi_page_t  mi_slice_t;
+typedef int64_t    mi_msecs_t;
+
+
+// Segments are large allocated memory blocks (8mb on 64 bit) from
 // the OS. Inside segments we allocated fixed size _pages_ that
 // contain blocks.
 typedef struct mi_segment_s {
-  // memory fields
-  size_t          memid;            // id for the os-level memory manager
-  bool            mem_is_fixed;     // `true` if we cannot decommit/reset/protect in this memory (i.e. when allocated using large OS pages)
-  bool            mem_is_committed; // `true` if the whole segment is eagerly committed
-
-  // segment fields
-  struct mi_segment_s* next;        // must be the first segment field -- see `segment.c:segment_alloc`
-  struct mi_segment_s* prev;
-  struct mi_segment_s* abandoned_next;
-  size_t          abandoned;        // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
-  size_t          abandoned_visits; // count how often this segment is visited in the abandoned list (to force reclaim it it is too long)
-
-  size_t          used;        // count of pages in use (`used <= capacity`)
-  size_t          capacity;    // count of available pages (`#free + used`)
-  size_t          segment_size;// for huge pages this may be different from `MI_SEGMENT_SIZE`
-  size_t          segment_info_size;  // space we are using from the first page for segment meta-data and possible guard pages.
-  uintptr_t       cookie;      // verify addresses in secure mode: `_mi_ptr_cookie(segment) == segment->cookie`
+  size_t            memid;              // memory id for arena allocation
+  bool              mem_is_pinned;      // `true` if we cannot decommit/reset/protect in this memory (i.e. when allocated using large OS pages)    
+  bool              mem_is_large;       // in large/huge os pages?
+  bool              mem_is_committed;   // `true` if the whole segment is eagerly committed
+
+  bool              allow_decommit;     
+  mi_msecs_t        decommit_expire;
+  mi_commit_mask_t  decommit_mask;
+  mi_commit_mask_t  commit_mask;
+
+  _Atomic(struct mi_segment_s*) abandoned_next;
+
+  // from here is zero initialized
+  struct mi_segment_s* next;            // the list of freed segments in the cache (must be first field, see `segment.c:mi_segment_init`)
+  
+  size_t            abandoned;          // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
+  size_t            abandoned_visits;   // count how often this segment is visited in the abandoned list (to force reclaim it it is too long)
+  size_t            used;               // count of pages in use
+  uintptr_t         cookie;             // verify addresses in debug mode: `mi_ptr_cookie(segment) == segment->cookie`  
+
+  size_t            segment_slices;      // for huge segments this may be different from `MI_SLICES_PER_SEGMENT`
+  size_t            segment_info_slices; // initial slices we are using segment info and possible guard pages.
 
   // layout like this to optimize access in `mi_free`
-  size_t          page_shift;  // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`).
-  volatile _Atomic(uintptr_t) thread_id;   // unique id of the thread owning this segment
-  mi_page_kind_t  page_kind;   // kind of pages: small, large, or huge
-  mi_page_t       pages[1];    // up to `MI_SMALL_PAGES_PER_SEGMENT` pages
+  mi_segment_kind_t kind;
+  _Atomic(mi_threadid_t) thread_id;      // unique id of the thread owning this segment
+  size_t            slice_entries;       // entries in the `slices` array, at most `MI_SLICES_PER_SEGMENT`
+  mi_slice_t        slices[MI_SLICES_PER_SEGMENT];
 } mi_segment_t;
 
 
@@ -301,7 +412,7 @@ typedef struct mi_random_cxt_s {
 } mi_random_ctx_t;
 
 
-// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows
+// In debug mode there is a padding structure at the end of the blocks to check for buffer overflows
 #if (MI_PADDING)
 typedef struct mi_padding_s {
   uint32_t canary; // encoded block value to check validity of the padding (in case of overflow)
@@ -322,8 +433,8 @@ struct mi_heap_s {
   mi_tld_t*             tld;
   mi_page_t*            pages_free_direct[MI_PAGES_DIRECT];  // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size.
   mi_page_queue_t       pages[MI_BIN_FULL + 1];              // queue of pages for each size class (or "bin")
-  volatile _Atomic(mi_block_t*) thread_delayed_free;
-  uintptr_t             thread_id;                           // thread this heap belongs too
+  _Atomic(mi_block_t*)  thread_delayed_free;
+  mi_threadid_t         thread_id;                           // thread this heap belongs too
   uintptr_t             cookie;                              // random cookie to verify pointers (see `_mi_ptr_cookie`)
   uintptr_t             keys[2];                             // two random keys used to encode the `thread_delayed_free` list
   mi_random_ctx_t       random;                              // random number context used for secure allocation
@@ -340,9 +451,15 @@ struct mi_heap_s {
 // Debug
 // ------------------------------------------------------
 
+#if !defined(MI_DEBUG_UNINIT)
 #define MI_DEBUG_UNINIT     (0xD0)
+#endif
+#if !defined(MI_DEBUG_FREED)
 #define MI_DEBUG_FREED      (0xDF)
+#endif
+#if !defined(MI_DEBUG_PADDING)
 #define MI_DEBUG_PADDING    (0xDE)
+#endif
 
 #if (MI_DEBUG)
 // use our own assertion to print without memory allocation
@@ -398,8 +515,9 @@ typedef struct mi_stats_s {
   mi_stat_count_t segments_abandoned;
   mi_stat_count_t pages_abandoned;
   mi_stat_count_t threads;
+  mi_stat_count_t normal;
   mi_stat_count_t huge;
-  mi_stat_count_t giant;
+  mi_stat_count_t large;
   mi_stat_count_t malloc;
   mi_stat_count_t segments_cache;
   mi_stat_counter_t pages_extended;
@@ -407,10 +525,11 @@ typedef struct mi_stats_s {
   mi_stat_counter_t commit_calls;
   mi_stat_counter_t page_no_retire;
   mi_stat_counter_t searches;
+  mi_stat_counter_t normal_count;
   mi_stat_counter_t huge_count;
-  mi_stat_counter_t giant_count;
+  mi_stat_counter_t large_count;
 #if MI_STAT>1
-  mi_stat_count_t normal[MI_BIN_HUGE+1];
+  mi_stat_count_t normal_bins[MI_BIN_HUGE+1];
 #endif
 } mi_stats_t;
 
@@ -429,6 +548,7 @@ void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount);
 #define mi_stat_counter_increase(stat,amount) (void)0
 #endif
 
+#define mi_heap_stat_counter_increase(heap,stat,amount)  mi_stat_counter_increase( (heap)->tld->stats.stat, amount)
 #define mi_heap_stat_increase(heap,stat,amount)  mi_stat_increase( (heap)->tld->stats.stat, amount)
 #define mi_heap_stat_decrease(heap,stat,amount)  mi_stat_decrease( (heap)->tld->stats.stat, amount)
 
@@ -436,13 +556,15 @@ void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount);
 // Thread Local data
 // ------------------------------------------------------
 
-typedef int64_t  mi_msecs_t;
+// A "span" is is an available range of slices. The span queues keep
+// track of slice spans of at most the given `slice_count` (but more than the previous size class).
+typedef struct mi_span_queue_s {
+  mi_slice_t* first;
+  mi_slice_t* last;
+  size_t      slice_count;
+} mi_span_queue_t;
 
-// Queue of segments
-typedef struct mi_segment_queue_s {
-  mi_segment_t* first;
-  mi_segment_t* last;
-} mi_segment_queue_t;
+#define MI_SEGMENT_BIN_MAX (35)     // 35 == mi_segment_bin(MI_SLICES_PER_SEGMENT)
 
 // OS thread local data
 typedef struct mi_os_tld_s {
@@ -450,18 +572,14 @@ typedef struct mi_os_tld_s {
   mi_stats_t*           stats;        // points to tld stats
 } mi_os_tld_t;
 
+
 // Segments thread local data
 typedef struct mi_segments_tld_s {
-  mi_segment_queue_t  small_free;   // queue of segments with free small pages
-  mi_segment_queue_t  medium_free;  // queue of segments with free medium pages
-  mi_page_queue_t     pages_reset;  // queue of freed pages that can be reset
+  mi_span_queue_t     spans[MI_SEGMENT_BIN_MAX+1];  // free slice spans inside segments
   size_t              count;        // current number of segments;
   size_t              peak_count;   // peak number of segments
   size_t              current_size; // current size of all segments
   size_t              peak_size;    // peak size of all segments
-  size_t              cache_count;  // number of segments in the cache
-  size_t              cache_size;   // total size of all segments in the cache
-  mi_segment_t*       cache;        // (small) cache of segments
   mi_stats_t*         stats;        // points to tld stats
   mi_os_tld_t*        os;           // points to os stats
 } mi_segments_tld_t;
index 8dd318cb7b91840a27d0bdb894c7c267a30cc1d0..c752ac247f3353b4e37fffebc6acb70efac4fdc8 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -8,7 +8,7 @@ terms of the MIT license. A copy of the license can be found in the file
 #ifndef MIMALLOC_H
 #define MIMALLOC_H
 
-#define MI_MALLOC_VERSION 164   // major + 2 digits minor
+#define MI_MALLOC_VERSION 206   // major + 2 digits minor
 
 // ------------------------------------------------------
 // Compiler specific attributes
@@ -24,9 +24,9 @@ terms of the MIT license. A copy of the license can be found in the file
   #define mi_attr_noexcept
 #endif
 
-#if (__cplusplus >= 201703)
+#if defined(__cplusplus) && (__cplusplus >= 201703)
   #define mi_decl_nodiscard    [[nodiscard]]
-#elif (__GNUC__ >= 4) || defined(__clang__)  // includes clang, icc, and clang-cl
+#elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)  // includes clang, icc, and clang-cl
   #define mi_decl_nodiscard    __attribute__((warn_unused_result))
 #elif (_MSC_VER >= 1700)
   #define mi_decl_nodiscard    _Check_return_
@@ -58,8 +58,12 @@ terms of the MIT license. A copy of the license can be found in the file
   #define mi_attr_alloc_size2(s1,s2)
   #define mi_attr_alloc_align(p)
 #elif defined(__GNUC__)                 // includes clang and icc
+  #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT)
+    #define mi_decl_export              __attribute__((visibility("default")))
+  #else
+    #define mi_decl_export
+  #endif
   #define mi_cdecl                      // leads to warnings... __attribute__((cdecl))
-  #define mi_decl_export                __attribute__((visibility("default")))
   #define mi_decl_restrict
   #define mi_attr_malloc                __attribute__((malloc))
   #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
@@ -153,12 +157,16 @@ mi_decl_export void mi_thread_init(void)      mi_attr_noexcept;
 mi_decl_export void mi_thread_done(void)      mi_attr_noexcept;
 mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
 
+mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, 
+                                    size_t* current_rss, size_t* peak_rss, 
+                                    size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept;
 
 // -------------------------------------------------------------------------------------
 // Aligned allocation
 // Note that `alignment` always follows `size` for consistency with unaligned
 // allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
 // -------------------------------------------------------------------------------------
+#define MI_ALIGNMENT_MAX   (1024*1024UL)    // maximum supported alignment is 1MiB
 
 mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
 mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
@@ -192,7 +200,7 @@ mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_
 mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
 
 mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize)              mi_attr_noexcept mi_attr_alloc_size(3);
-mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size)  mi_attr_noexcept mi_attr_alloc_size2(3,4);;
+mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size)  mi_attr_noexcept mi_attr_alloc_size2(3,4);
 mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize)             mi_attr_noexcept mi_attr_alloc_size(3);
 
 mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s)            mi_attr_noexcept mi_attr_malloc;
@@ -246,8 +254,9 @@ typedef struct mi_heap_area_s {
   void*  blocks;      // start of the area containing heap blocks
   size_t reserved;    // bytes reserved for this area (virtual)
   size_t committed;   // current available bytes for this area
-  size_t used;        // bytes in use by allocated blocks
+  size_t used;        // number of allocated blocks
   size_t block_size;  // size in bytes of each block
+  size_t full_block_size; // size in bytes of a full block including padding and metadata.
 } mi_heap_area_t;
 
 typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg);
@@ -256,11 +265,16 @@ mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_b
 
 // Experimental
 mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
-mi_decl_nodiscard mi_decl_export bool mi_is_redirected() mi_attr_noexcept;
+mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept;
 
 mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
 mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
 
+mi_decl_export int  mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
+mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept;
+
+mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept;
+
 // deprecated
 mi_decl_export int  mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
 
@@ -285,7 +299,7 @@ mi_decl_export int  mi_reserve_huge_os_pages(size_t pages, double max_secs, size
 
 
 // ------------------------------------------------------
-// Options, all `false` by default
+// Options
 // ------------------------------------------------------
 
 typedef enum mi_option_e {
@@ -293,21 +307,30 @@ typedef enum mi_option_e {
   mi_option_show_errors,
   mi_option_show_stats,
   mi_option_verbose,
-  // the following options are experimental
+  // some of the following options are experimental
+  // (deprecated options are kept for binary backward compatibility with v1.x versions)
   mi_option_eager_commit,
-  mi_option_eager_region_commit,
-  mi_option_reset_decommits,
-  mi_option_large_os_pages,         // implies eager commit
-  mi_option_reserve_huge_os_pages,
-  mi_option_segment_cache,
+  mi_option_deprecated_eager_region_commit,
+  mi_option_deprecated_reset_decommits,
+  mi_option_large_os_pages,           // use large (2MiB) OS pages, implies eager commit
+  mi_option_reserve_huge_os_pages,    // reserve N huge OS pages (1GiB) at startup
+  mi_option_reserve_huge_os_pages_at, // reserve huge OS pages at a specific NUMA node
+  mi_option_reserve_os_memory,        // reserve specified amount of OS memory at startup
+  mi_option_deprecated_segment_cache,
   mi_option_page_reset,
-  mi_option_abandoned_page_reset,
-  mi_option_segment_reset,
+  mi_option_abandoned_page_decommit,
+  mi_option_deprecated_segment_reset,
   mi_option_eager_commit_delay,
-  mi_option_reset_delay,
-  mi_option_use_numa_nodes,
+  mi_option_decommit_delay,
+  mi_option_use_numa_nodes,           // 0 = use available numa nodes, otherwise use at most N nodes.
+  mi_option_limit_os_alloc,           // 1 = do not use OS memory for allocation (but only reserved arenas)
   mi_option_os_tag,
   mi_option_max_errors,
+  mi_option_max_warnings,
+  mi_option_max_segment_reclaim,
+  mi_option_allow_decommit,
+  mi_option_segment_decommit_delay,  
+  mi_option_decommit_extend_delay,
   _mi_option_last
 } mi_option_t;
 
@@ -319,6 +342,7 @@ mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
 mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
 
 mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
+mi_decl_nodiscard mi_decl_export long mi_option_get_clamp(mi_option_t option, long min, long max);
 mi_decl_export void mi_option_set(mi_option_t option, long value);
 mi_decl_export void mi_option_set_default(mi_option_t option, long value);
 
@@ -332,6 +356,7 @@ mi_decl_export void mi_option_set_default(mi_option_t option, long value);
 mi_decl_export void  mi_cfree(void* p) mi_attr_noexcept;
 mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
 mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p)        mi_attr_noexcept;
+mi_decl_nodiscard mi_decl_export size_t mi_malloc_good_size(size_t size)     mi_attr_noexcept;
 mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
 
 mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size)   mi_attr_noexcept;
@@ -341,6 +366,7 @@ mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size)
 mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
 
 mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
+mi_decl_nodiscard mi_decl_export int   mi_reallocarr(void* p, size_t count, size_t size) mi_attr_noexcept;
 mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
 mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
 
@@ -373,6 +399,7 @@ mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount,
 // ---------------------------------------------------------------------------------------------
 #ifdef __cplusplus
 
+#include <cstddef>     // std::size_t
 #include <cstdint>     // PTRDIFF_MAX
 #if (__cplusplus >= 201103L) || (_MSC_VER > 1900)  // C++11
 #include <type_traits> // std::true_type
index daf57f39e73361bf44d6c52b87437e6093b43a2f..2e5a28824d5f8ca0161f58cb49a6fdcb26517cd0 100644 (file)
 mimalloc (pronounced "me-malloc")
 is a general purpose allocator with excellent [performance](#performance) characteristics.
 Initially developed by Daan Leijen for the run-time systems of the
-[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages.
-Latest release:`v1.6.4` (2020-08-06).
+[Koka](https://koka-lang.github.io) and [Lean](https://github.com/leanprover/lean) languages.
 
-It is a drop-in replacement for `malloc` and can be used in other programs
+Latest release tag: `v2.0.5` (alpha, 2022-02-14).  
+Latest stable  tag: `v1.7.5` (2022-02-14).
+
+mimalloc is a drop-in replacement for `malloc` and can be used in other programs
 without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as:
 ```
-> LD_PRELOAD=/usr/bin/libmimalloc.so  myprogram
+> LD_PRELOAD=/usr/lib/libmimalloc.so  myprogram
 ```
-It also has an easy way to override the allocator in [Windows](#override_on_windows). Notable aspects of the design include:
+It also has an easy way to override the default allocator in [Windows](#override_on_windows). Notable aspects of the design include:
 
-- __small and consistent__: the library is about 6k LOC using simple and
+- __small and consistent__: the library is about 8k LOC using simple and
   consistent data structures. This makes it very suitable
   to integrate and adapt in other projects. For runtime systems it
   provides hooks for a monotonic _heartbeat_ and deferred freeing (for
   bounded worst-case times with reference counting).
-- __free list sharding__: the big idea: instead of one big free list (per size class) we have
-  many smaller lists per memory "page" which both reduces fragmentation
-  and increases locality --
+- __free list sharding__: instead of one big free list (per size class) we have
+  many smaller lists per "mimalloc page" which reduces fragmentation and
+  increases locality --
   things that are allocated close in time get allocated close in memory.
-  (A memory "page" in _mimalloc_ contains blocks of one size class and is
-  usually 64KiB on a 64-bit system).
+  (A mimalloc page contains blocks of one size class and is usually 64KiB on a 64-bit system).
+- __free list multi-sharding__: the big idea! Not only do we shard the free list
+  per mimalloc page, but for each page we have multiple free lists. In particular, there
+  is one list for thread-local `free` operations, and another one for concurrent `free`
+  operations. Free-ing from another thread can now be a single CAS without needing
+  sophisticated coordination between threads. Since there will be 
+  thousands of separate free lists, contention is naturally distributed over the heap,
+  and the chance of contending on a single location will be low -- this is quite
+  similar to randomized algorithms like skip lists where adding
+  a random oracle removes the need for a more complex algorithm.
 - __eager page reset__: when a "page" becomes empty (with increased chance
   due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged")
   reducing (real) memory pressure and fragmentation, especially in long running
@@ -46,7 +56,7 @@ It also has an easy way to override the allocator in [Windows](#override_on_wind
   and has no internal points of contention using only atomic operations.
 - __fast__: In our benchmarks (see [below](#performance)),
   _mimalloc_ outperforms other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc),
-  and usually uses less memory (up to 25% more in the worst case). A nice property
+  and often uses less memory. A nice property
   is that it does consistently well over a wide range of benchmarks. There is also good huge OS page
   support for larger server programs.
 
@@ -55,43 +65,72 @@ You can read more on the design of _mimalloc_ in the [technical report](https://
 
 Enjoy!  
 
+### Branches
+
+* `master`: latest stable release.
+* `dev`: development branch for mimalloc v1.
+* `dev-slice`: development branch for mimalloc v2 with a new algorithm for managing internal mimalloc pages.
+
 ### Releases
 
-* 2020-08-06, `v1.6.4`: stable release 1.6: improved error recovery in low-memory situations,
-  support for IllumOS and Haiku, NUMA support for Vista/XP, improved NUMA detection for AMD Ryzen, ubsan support.
-* 2020-05-05, `v1.6.3`: stable release 1.6: improved behavior in out-of-memory situations, improved malloc zones on macOS,
-  build PIC static libraries by default, add option to abort on out-of-memory, line buffered statistics.
-* 2020-04-20, `v1.6.2`: stable release 1.6: fix compilation on Android, MingW, Raspberry, and Conda,
-  stability fix for Windows 7, fix multiple mimalloc instances in one executable, fix `strnlen` overload,
-  fix aligned debug padding.
-* 2020-02-17, `v1.6.1`: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects).
-* 2020-02-09, `v1.6.0`: stable release 1.6: fixed potential memory leak, improved overriding
-  and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise
-  heap block overflow detection in debug mode (besides the double-free detection and free-list
-  corruption detection). Add `nodiscard` attribute to most allocation functions.
-  Enable `MIMALLOC_PAGE_RESET` by default. New reclamation strategy for abandoned heap pages
-  for better memory footprint.
-* 2020-02-09, `v1.5.0`: stable release 1.5: improved free performance, small bug fixes.
-* 2020-01-22, `v1.4.0`: stable release 1.4: improved performance for delayed OS page reset,
-more eager concurrent free, addition of STL allocator, fixed potential memory leak.
-* 2020-01-15, `v1.3.0`: stable release 1.3: bug fixes, improved randomness and [stronger
-free list encoding](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396) in secure mode.
-* 2019-12-22, `v1.2.2`: stable release 1.2: minor updates.
-* 2019-11-22, `v1.2.0`: stable release 1.2: bug fixes, improved secure mode (free list corruption checks, double free mitigation). Improved dynamic overriding on Windows.
-* 2019-10-07, `v1.1.0`: stable release 1.1.
-* 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support.
-* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements.
+Note: the `v2.x` beta has a new algorithm for managing internal mimalloc pages that tends to use reduce memory usage
+  and fragmentation compared to mimalloc `v1.x` (especially for large workloads). Should otherwise have similar performance
+  (see [below](#performance)); please report if you observe any significant performance regression.
+
+* 2022-02-14, `v1.7.5`, `v2.0.5` (alpha): fix malloc override on
+  Windows 11, fix compilation with musl, potentially reduced
+  committed memory, add `bin/minject` for Windows, 
+  improved wasm support, faster aligned allocation,
+  various small fixes.
+
+* 2021-11-14, `v1.7.3`, `v2.0.3` (beta): improved WASM support, improved macOS support and performance (including
+  M1), improved performance for v2 for large objects, Python integration improvements, more standard
+  installation directories, various small fixes.
+
+* 2021-06-17, `v1.7.2`, `v2.0.2` (beta): support M1, better installation layout on Linux, fix
+  thread_id on Android, prefer 2-6TiB area for aligned allocation to work better on pre-windows 8, various small fixes.
+
+* 2021-04-06, `v1.7.1`, `v2.0.1` (beta): fix bug in arena allocation for huge pages, improved aslr on large allocations, initial M1 support (still experimental).
+  
+* 2021-01-31, `v2.0.0`: beta release 2.0: new slice algorithm for managing internal mimalloc pages.
+  
+* 2021-01-31, `v1.7.0`: stable release 1.7: support explicit user provided memory regions, more precise statistics,
+  improve macOS overriding, initial support for Apple M1, improved DragonFly support, faster memcpy on Windows, various small fixes.
+
+* [Older release notes](#older-release-notes)
 
 Special thanks to:
 
-* Jason Gibson (@jasongibson) for exhaustive testing on large workloads and server environments and finding complex bugs in (early versions of) `mimalloc`.
-* Manuel Pöter (@mpoeter) and Sam Gross (@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation.
+* [David Carlier](https://devnexen.blogspot.com/) (@devnexen) for his many contributions, and making
+  mimalloc work better on many less common operating systems, like Haiku, Dragonfly, etc.
+* Mary Feofanova (@mary3000), Evgeniy Moiseenko, and Manuel Pöter (@mpoeter) for making mimalloc TSAN checkable, and finding
+  memory model bugs using the [genMC] model checker.
+* Weipeng Liu (@pongba), Zhuowei Li, Junhua Wang, and Jakub Szymanski, for their early support of mimalloc and deployment
+  at large scale services, leading to many improvements in the mimalloc algorithms for large workloads.
+* Jason Gibson (@jasongibson) for exhaustive testing on large scale workloads and server environments, and finding complex bugs 
+  in (early versions of) `mimalloc`.
+* Manuel Pöter (@mpoeter) and Sam Gross(@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation. Sam also created the [no GIL](https://github.com/colesbury/nogil) Python fork which 
+  uses mimalloc internally.
+
+
+[genMC]: https://plv.mpi-sws.org/genmc/
+
+### Usage
+
+mimalloc is used in various large scale low-latency services and programs, for example:
+
+<a href="https://www.bing.com"><img height="50" align="left" src="https://upload.wikimedia.org/wikipedia/commons/e/e9/Bing_logo.svg"></a>
+<a href="https://azure.microsoft.com/"><img height="50" align="left" src="https://upload.wikimedia.org/wikipedia/commons/a/a8/Microsoft_Azure_Logo.svg"></a>
+<a href="https://deathstrandingpc.505games.com"><img height="100" src="doc/ds-logo.png"></a>
+<a href="https://docs.unrealengine.com/4.26/en-US/WhatsNew/Builds/ReleaseNotes/4_25/"><img height="100" src="doc/unreal-logo.svg"></a>
+<a href="https://cab.spbu.ru/software/spades/"><img height="100" src="doc/spades-logo.png"></a>
+
 
 # Building
 
 ## Windows
 
-Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`).
+Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build.
 The `mimalloc` project builds a static library (in `out/msvc-x64`), while the
 `mimalloc-override` project builds a DLL for overriding malloc
 in the entire program.
@@ -140,6 +179,11 @@ Notes:
 2. Install CCMake: `sudo apt-get install cmake-curses-gui`
 
 
+## Single source
+
+You can also directly build the single `src/static.c` file as part of your project without
+needing `cmake` at all. Make sure to also add the mimalloc `include` directory to the include path.
+
 
 # Using the library
 
@@ -215,7 +259,7 @@ completely and redirect all calls to the _mimalloc_ library instead .
 ## Environment Options
 
 You can set further options either programmatically (using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
-or via environment variables.
+or via environment variables:
 
 - `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
 - `MIMALLOC_VERBOSE=1`: show verbose messages.
@@ -251,6 +295,9 @@ or via environment variables.
    `MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB)
    of a thread to not allocate in the huge OS pages; this prevents threads that are short lived
    and allocate just a little to take up space in the huge OS page area (which cannot be reset).
+   The huge pages are usually allocated evenly among NUMA nodes.
+   We can use `MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N` where `N` is the numa node (starting at 0) to allocate all 
+   the huge pages at a specific numa node instead. 
 
 Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
 for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
@@ -265,11 +312,11 @@ _mimalloc_ can be build in secure mode by using the `-DMI_SECURE=ON` flags in `c
 to make mimalloc more robust against exploits. In particular:
 
 - All internal mimalloc pages are surrounded by guard pages and the heap metadata is behind a guard page as well (so a buffer overflow
-  exploit cannot reach into the metadata),
+  exploit cannot reach into the metadata).
 - All free list pointers are
   [encoded](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396)
-  with per-page keys which is used both to prevent overwrites with a known pointer, as well as to detect heap corruption,
-- Double free's are detected (and ignored),
+  with per-page keys which is used both to prevent overwrites with a known pointer, as well as to detect heap corruption.
+- Double free's are detected (and ignored).
 - The free lists are initialized in a random order and allocation randomly chooses between extension and reuse within a page to
   mitigate against attacks that rely on a predicable allocation order. Similarly, the larger heap blocks allocated by mimalloc
   from the OS are also address randomized.
@@ -286,9 +333,9 @@ When _mimalloc_ is built using debug mode, various checks are done at runtime to
 - Corrupted free-lists and some forms of use-after-free are detected.
 
 
-# Overriding Malloc
+# Overriding Standard Malloc
 
-Overriding the standard `malloc` can be done either _dynamically_ or _statically_.
+Overriding the standard `malloc` (and `new`) can be done either _dynamically_ or _statically_.
 
 ## Dynamic override
 
@@ -319,13 +366,12 @@ On macOS we can also preload the mimalloc shared
 library so all calls to the standard `malloc` interface are
 resolved to the _mimalloc_ library.
 ```
-> env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram
+> env DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram
 ```
 
 Note that certain security restrictions may apply when doing this from
 the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash).
 
-(Note: macOS support for dynamic overriding is recent, please report any issues.)
 
 ### Override on Windows
 
@@ -335,7 +381,7 @@ the (dynamic) C runtime allocator, including those from other DLL's or libraries
 
 The overriding on Windows requires that you link your program explicitly with
 the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
-Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be available
+Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be put
 in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
 The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
 mimalloc (in `mimalloc-override.dll`).
@@ -378,7 +424,7 @@ under your control or otherwise mixing of pointers from different heaps may occu
 
 # Performance
 
-Last update: 2020-01-20
+Last update: 2021-01-30
 
 We tested _mimalloc_ against many other top allocators over a wide
 range of benchmarks, ranging from various real world programs to
@@ -395,10 +441,15 @@ suffering from (too much) underperformance in less common situations.
 
 As always, interpret these results with care since some benchmarks test synthetic
 or uncommon situations that may never apply to your workloads. For example, most
-allocators do not do well on `xmalloc-testN` but that includes the best
+allocators do not do well on `xmalloc-testN` but that includes even the best
 industrial allocators like _jemalloc_ and _tcmalloc_ that are used in some of
 the world's largest systems (like Chrome or FreeBSD).
 
+Also, the benchmarks here do not measure the behaviour on very large and long-running server workloads,
+or worst-case latencies of allocation. Much work has gone into `mimalloc` to work well on such
+workloads (for example, to reduce virtual memory fragmentation on long-running services)
+but such optimizations are not always reflected in the current benchmark suite.
+
 We show here only an overview -- for
 more specific details and further benchmarks we refer to the
 [technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action).
@@ -406,27 +457,28 @@ The benchmark suite is automated and available separately
 as [mimalloc-bench](https://github.com/daanx/mimalloc-bench).
 
 
-## Benchmark Results on 36-core Intel
+## Benchmark Results on a 16-core AMD 5950x (Zen3)
 
-Testing on a big Amazon EC2 compute instance
-([c5.18xlarge](https://aws.amazon.com/ec2/instance-types/#Compute_Optimized))
-consisting of a 72 processor Intel Xeon at 3GHz
-with 144GiB ECC memory, running        Ubuntu 18.04.1 with glibc 2.27 and GCC 7.4.0.
-The measured allocators are _mimalloc_ (xmi, tag:v1.4.0, page reset enabled)
-and its secure build as _smi_,
-Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (tc, tag:gperftools-2.7) used in Chrome,
-Facebook's [_jemalloc_](https://github.com/jemalloc/jemalloc) (je, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD,
-the Intel thread building blocks [allocator](https://github.com/intel/tbb) (tbb, tag:2020),
-[rpmalloc](https://github.com/mjansson/rpmalloc) (rp,tag:1.4.0) by Mattias Jansson,
-the original scalable [_Hoard_](https://github.com/emeryberger/Hoard) (tag:3.13) allocator by Emery Berger \[1],
-the memory compacting [_Mesh_](https://github.com/plasma-umass/Mesh) (git:51222e7) allocator by
+Testing on the 16-core AMD 5950x processor at 3.4Ghz (4.9Ghz boost), with
+with 32GiB memory at 3600Mhz, running  Ubuntu 20.04 with glibc 2.31 and GCC 9.3.0.
+
+We measure three versions of _mimalloc_: the main version `mi` (tag:v1.7.0),
+the new v2.0 beta version as `xmi` (tag:v2.0.0), and the main version in secure mode as `smi` (tag:v1.7.0).
+
+The other allocators are
+Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (`tc`, tag:gperftools-2.8.1) used in Chrome,
+Facebook's [_jemalloc_](https://github.com/jemalloc/jemalloc) (`je`, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD,
+the Intel thread building blocks [allocator](https://github.com/intel/tbb) (`tbb`, tag:v2020.3),
+[rpmalloc](https://github.com/mjansson/rpmalloc) (`rp`,tag:1.4.1) by Mattias Jansson,
+the original scalable [_Hoard_](https://github.com/emeryberger/Hoard) (git:d880f72) allocator by Emery Berger \[1],
+the memory compacting [_Mesh_](https://github.com/plasma-umass/Mesh) (git:67ff31a) allocator by
 Bobby Powers _et al_ \[8],
-and finally the default system allocator (glibc, 2.27) (based on _PtMalloc2_).
+and finally the default system allocator (`glibc`, 2.31) (based on _PtMalloc2_).
 
-<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-a.svg"/>
-<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-b.svg"/>
+<img width="90%" src="doc/bench-2021/bench-amd5950x-2021-01-30-a.svg"/>
+<img width="90%" src="doc/bench-2021/bench-amd5950x-2021-01-30-b.svg"/>
 
-Any benchmarks ending in `N` run on all processors in parallel.
+Any benchmarks ending in `N` run on all 32 logical cores in parallel.
 Results are averaged over 10 runs and reported relative
 to mimalloc (where 1.2 means it took 1.2&times; longer to run).
 The legend also contains the _overall relative score_ between the
@@ -441,18 +493,17 @@ _jemalloc_.
 
 The _leanN_ program is interesting as a large realistic and
 concurrent workload of the [Lean](https://github.com/leanprover/lean)
-theorem prover compiling its own standard library, and there is a 7%
+theorem prover compiling its own standard library, and there is a 13%
 speedup over _tcmalloc_. This is
 quite significant: if Lean spends 20% of its time in the
-allocator that means that _mimalloc_ is 1.3&times; faster than _tcmalloc_
+allocator that means that _mimalloc_ is 1.6&times; faster than _tcmalloc_
 here. (This is surprising as that is not measured in a pure
 allocation benchmark like _alloc-test_. We conjecture that we see this
 outsized improvement here because _mimalloc_ has better locality in
 the allocation which improves performance for the *other* computations
 in a program as well).
 
-The single threaded _redis_ benchmark again show that most allocators do well on such workloads where _tcmalloc_
-did best this time.
+The single threaded _redis_ benchmark again show that most allocators do well on such workloads.
 
 The _larsonN_ server benchmark by Larson and Krishnan \[2] allocates and frees between threads. They observed this
 behavior (which they call _bleeding_) in actual server applications, and the benchmark simulates this.
@@ -476,14 +527,12 @@ The _alloc-test_, by
 [OLogN Technologies AG](http://ithare.com/testing-memory-allocators-ptmalloc2-tcmalloc-hoard-jemalloc-while-trying-to-simulate-real-world-loads/), is a very allocation intensive benchmark doing millions of
 allocations in various size classes. The test is scaled such that when an
 allocator performs almost identically on _alloc-test1_ as _alloc-testN_ it
-means that it scales linearly. Here, _tcmalloc_, and
-_Hoard_ seem to scale less well and do more than 10% worse on the multi-core version. Even the best industrial
-allocators (_tcmalloc_, _jemalloc_, and _tbb_) are more than 10% slower as _mimalloc_ here.
+means that it scales linearly. 
 
 The _sh6bench_ and _sh8bench_ benchmarks are
 developed by [MicroQuill](http://www.microquill.com/) as part of SmartHeap.
 In _sh6bench_ _mimalloc_ does much
-better than the others (more than 1.5&times; faster than _jemalloc_).
+better than the others (more than 2.5&times; faster than _jemalloc_).
 We cannot explain this well but believe it is
 caused in part by the "reverse" free-ing pattern in _sh6bench_.
 The _sh8bench_ is a variation with object migration
@@ -493,7 +542,7 @@ The _xmalloc-testN_ benchmark by Lever and Boreham \[5] and Christian Eder, simu
 some threads only allocate, and others only free -- they observed this pattern in
 larger server applications. Here we see that
 the _mimalloc_ technique of having non-contended sharded thread free
-lists pays off as it outperforms others by a very large margin. Only _rpmalloc_ and _tbb_ also scale well on this benchmark.
+lists pays off as it outperforms others by a very large margin. Only _rpmalloc_, _tbb_, and _glibc_ also scale well on this benchmark.
 
 The _cache-scratch_ benchmark by Emery Berger \[1], and introduced with
 the Hoard allocator to test for _passive-false_ sharing of cache lines.
@@ -507,16 +556,20 @@ cache line sharing completely, while _Hoard_ and _glibc_ seem to mitigate
 the effects. Kukanov and Voss \[7] describe in detail
 how the design of _tbb_ avoids the false cache line sharing.
 
-## On 24-core AMD Epyc
 
-For completeness, here are the results on a
-[r5a.12xlarge](https://aws.amazon.com/ec2/instance-types/#Memory_Optimized) instance
-having a 48 processor AMD Epyc 7000 at 2.5GHz with 384GiB of memory.
-The results are similar to the Intel results but it is interesting to
+## On a 36-core Intel Xeon
+
+For completeness, here are the results on a big Amazon
+[c5.18xlarge](https://aws.amazon.com/ec2/instance-types/#Compute_Optimized) instance
+consisting of a 2&times;18-core Intel Xeon (Cascade Lake) at 3.4GHz (boost 3.5GHz)
+with 144GiB ECC memory, running        Ubuntu 20.04 with glibc 2.31, GCC 9.3.0, and
+Clang 10.0.0. This time, the mimalloc allocators (mi, xmi, and smi) were
+compiled with the Clang compiler instead of GCC.
+The results are similar to the AMD results but it is interesting to
 see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks.
 
-<img width="90%" src="doc/bench-r5a-12xlarge-2020-01-16-a.svg"/>
-<img width="90%" src="doc/bench-r5a-12xlarge-2020-01-16-b.svg"/>
+<img width="90%" src="doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg"/>
+<img width="90%" src="doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg"/>
 
 
 ## Peak Working Set
@@ -524,14 +577,59 @@ see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks
 The following figure shows the peak working set (rss) of the allocators
 on the benchmarks (on the c5.18xlarge instance).
 
-<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-rss-a.svg"/>
-<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-rss-b.svg"/>
+<img width="90%" src="doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg"/>
+<img width="90%" src="doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg"/>
 
 Note that the _xmalloc-testN_ memory usage should be disregarded as it
 allocates more the faster the program runs. Similarly, memory usage of
-_mstressN_, _rptestN_ and _sh8bench_ can vary depending on scheduling and
-speed. Nevertheless, even though _mimalloc_ is fast on these benchmarks we
-believe the memory usage is too high and hope to improve.
+_larsonN_, _mstressN_, _rptestN_ and _sh8bench_ can vary depending on scheduling and
+speed. Nevertheless, we hope to improve the memory usage on _mstressN_
+and _rptestN_ (just as _cfrac_, _larsonN_ and _sh8bench_ have a small working set which skews the results).
+
+<!--
+# Previous Benchmarks
+
+Todo: should we create a separate page for this?
+
+## Benchmark Results on 36-core Intel: 2020-01-20
+
+Testing on a big Amazon EC2 compute instance
+([c5.18xlarge](https://aws.amazon.com/ec2/instance-types/#Compute_Optimized))
+consisting of a 72 processor Intel Xeon at 3GHz
+with 144GiB ECC memory, running        Ubuntu 18.04.1 with glibc 2.27 and GCC 7.4.0.
+The measured allocators are _mimalloc_ (xmi, tag:v1.4.0, page reset enabled)
+and its secure build as _smi_,
+Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (tc, tag:gperftools-2.7) used in Chrome,
+Facebook's [_jemalloc_](https://github.com/jemalloc/jemalloc) (je, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD,
+the Intel thread building blocks [allocator](https://github.com/intel/tbb) (tbb, tag:2020),
+[rpmalloc](https://github.com/mjansson/rpmalloc) (rp,tag:1.4.0) by Mattias Jansson,
+the original scalable [_Hoard_](https://github.com/emeryberger/Hoard) (tag:3.13) allocator by Emery Berger \[1],
+the memory compacting [_Mesh_](https://github.com/plasma-umass/Mesh) (git:51222e7) allocator by
+Bobby Powers _et al_ \[8],
+and finally the default system allocator (glibc, 2.27) (based on _PtMalloc2_).
+
+<img width="90%" src="doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg"/>
+<img width="90%" src="doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg"/>
+
+The following figure shows the peak working set (rss) of the allocators
+on the benchmarks (on the c5.18xlarge instance).
+
+<img width="90%" src="doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg"/>
+<img width="90%" src="doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg"/>
+
+
+## On 24-core AMD Epyc, 2020-01-16
+
+For completeness, here are the results on a
+[r5a.12xlarge](https://aws.amazon.com/ec2/instance-types/#Memory_Optimized) instance
+having a 48 processor AMD Epyc 7000 at 2.5GHz with 384GiB of memory.
+The results are similar to the Intel results but it is interesting to
+see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks.
+
+<img width="90%" src="doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg"/>
+<img width="90%" src="doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg"/>
+
+-->
 
 
 # References
@@ -571,7 +669,6 @@ believe the memory usage is too high and hope to improve.
   In Proceedings of the 2019 ACM SIGPLAN International Symposium on Memory Management, 122–135. ACM. 2019.
 -->
 
-
 # Contributing
 
 This project welcomes contributions and suggestions.  Most contributions require you to agree to a
@@ -581,3 +678,34 @@ the rights to use your contribution. For details, visit https://cla.microsoft.co
 When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
 a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
 provided by the bot. You will only need to do this once across all repos using our CLA.
+
+
+# Older Release Notes
+
+* 2020-09-24, `v1.6.7`: stable release 1.6: using standard C atomics, passing tsan testing, improved
+  handling of failing to commit on Windows, add [`mi_process_info`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc.h#L156) api call.
+* 2020-08-06, `v1.6.4`: stable release 1.6: improved error recovery in low-memory situations,
+  support for IllumOS and Haiku, NUMA support for Vista/XP, improved NUMA detection for AMD Ryzen, ubsan support.
+* 2020-05-05, `v1.6.3`: stable release 1.6: improved behavior in out-of-memory situations, improved malloc zones on macOS,
+  build PIC static libraries by default, add option to abort on out-of-memory, line buffered statistics.
+* 2020-04-20, `v1.6.2`: stable release 1.6: fix compilation on Android, MingW, Raspberry, and Conda,
+  stability fix for Windows 7, fix multiple mimalloc instances in one executable, fix `strnlen` overload,
+  fix aligned debug padding.
+* 2020-02-17, `v1.6.1`: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects).
+* 2020-02-09, `v1.6.0`: stable release 1.6: fixed potential memory leak, improved overriding
+  and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise
+  heap block overflow detection in debug mode (besides the double-free detection and free-list
+  corruption detection). Add `nodiscard` attribute to most allocation functions.
+  Enable `MIMALLOC_PAGE_RESET` by default. New reclamation strategy for abandoned heap pages
+  for better memory footprint.
+* 2020-02-09, `v1.5.0`: stable release 1.5: improved free performance, small bug fixes.
+* 2020-01-22, `v1.4.0`: stable release 1.4: improved performance for delayed OS page reset,
+more eager concurrent free, addition of STL allocator, fixed potential memory leak.
+* 2020-01-15, `v1.3.0`: stable release 1.3: bug fixes, improved randomness and [stronger
+free list encoding](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396) in secure mode.
+* 2019-12-22, `v1.2.2`: stable release 1.2: minor updates.
+* 2019-11-22, `v1.2.0`: stable release 1.2: bug fixes, improved secure mode (free list corruption checks, double free mitigation). Improved dynamic overriding on Windows.
+* 2019-10-07, `v1.1.0`: stable release 1.1.
+* 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support.
+* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements.
+
index ca16d3676c2dd5780d8a505f737260a5d12e0dcb..fce0fd749852714026f513043e66656130ffae20 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -8,45 +8,28 @@ terms of the MIT license. A copy of the license can be found in the file
 #include "mimalloc.h"
 #include "mimalloc-internal.h"
 
-#include <string.h>  // memset, memcpy
+#include <string.h>  // memset
 
 // ------------------------------------------------------
 // Aligned Allocation
 // ------------------------------------------------------
 
-static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept {
-  // note: we don't require `size > offset`, we just guarantee that
-  // the address at offset is aligned regardless of the allocated size.
-  mi_assert(alignment > 0);
-  if (mi_unlikely(size > PTRDIFF_MAX)) return NULL;   // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)
-  if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>)
+// Fallback primitive aligned allocation -- split out for better codegen
+static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept
+{
+  mi_assert_internal(size <= PTRDIFF_MAX);
+  mi_assert_internal(alignment!=0 && _mi_is_power_of_two(alignment) && alignment <= MI_ALIGNMENT_MAX);
+
   const uintptr_t align_mask = alignment-1;  // for any x, `(x & align_mask) == (x % alignment)`
-  
-  // try if there is a small block available with just the right alignment
   const size_t padsize = size + MI_PADDING_SIZE;
-  if (mi_likely(padsize <= MI_SMALL_SIZE_MAX)) {
-    mi_page_t* page = _mi_heap_get_free_small_page(heap,padsize);
-    const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0;
-    if (mi_likely(page->free != NULL && is_aligned))
-    {
-      #if MI_STAT>1
-      mi_heap_stat_increase( heap, malloc, size);
-      #endif
-      void* p = _mi_page_malloc(heap,page,padsize); // TODO: inline _mi_page_malloc
-      mi_assert_internal(p != NULL);
-      mi_assert_internal(((uintptr_t)p + offset) % alignment == 0);
-      if (zero) _mi_block_zero_init(page,p,size);
-      return p;
-    }
-  }
 
   // use regular allocation if it is guaranteed to fit the alignment constraints
-  if (offset==0 && alignment<=padsize && padsize<=MI_MEDIUM_OBJ_SIZE_MAX && (padsize&align_mask)==0) {
+  if (offset==0 && alignment<=padsize && padsize<=MI_MAX_ALIGN_GUARANTEE && (padsize&align_mask)==0) {
     void* p = _mi_heap_malloc_zero(heap, size, zero);
     mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0);
     return p;
   }
-  
+
   // otherwise over-allocate
   void* p = _mi_heap_malloc_zero(heap, size + alignment - 1, zero);
   if (p == NULL) return NULL;
@@ -55,21 +38,90 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
   uintptr_t adjust = alignment - (((uintptr_t)p + offset) & align_mask);
   mi_assert_internal(adjust <= alignment);
   void* aligned_p = (adjust == alignment ? p : (void*)((uintptr_t)p + adjust));
-  if (aligned_p != p) mi_page_set_has_aligned(_mi_ptr_page(p), true); 
+  if (aligned_p != p) mi_page_set_has_aligned(_mi_ptr_page(p), true);
   mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0);
-  mi_assert_internal( p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p),_mi_ptr_page(aligned_p),aligned_p) );
+  mi_assert_internal(p == _mi_page_ptr_unalign(_mi_ptr_segment(aligned_p), _mi_ptr_page(aligned_p), aligned_p));
   return aligned_p;
 }
 
+// Primitive aligned allocation
+static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero) mi_attr_noexcept
+{
+  // note: we don't require `size > offset`, we just guarantee that the address at offset is aligned regardless of the allocated size.
+  mi_assert(alignment > 0);
+  if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) { // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>)
+    #if MI_DEBUG > 0
+    _mi_error_message(EOVERFLOW, "aligned allocation requires the alignment to be a power-of-two (size %zu, alignment %zu)\n", size, alignment);
+    #endif
+    return NULL;
+  }
+  if (mi_unlikely(alignment > MI_ALIGNMENT_MAX)) {  // we cannot align at a boundary larger than this (or otherwise we cannot find segment headers)
+    #if MI_DEBUG > 0
+    _mi_error_message(EOVERFLOW, "aligned allocation has a maximum alignment of %zu (size %zu, alignment %zu)\n", MI_ALIGNMENT_MAX, size, alignment);
+    #endif
+    return NULL;
+  }
+  if (mi_unlikely(size > PTRDIFF_MAX)) {          // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)                                                    
+    #if MI_DEBUG > 0
+    _mi_error_message(EOVERFLOW, "aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment);
+    #endif
+    return NULL;
+  }
+  const uintptr_t align_mask = alignment-1;       // for any x, `(x & align_mask) == (x % alignment)`
+  const size_t padsize = size + MI_PADDING_SIZE;  // note: cannot overflow due to earlier size > PTRDIFF_MAX check
+
+  // try first if there happens to be a small block available with just the right alignment
+  if (mi_likely(padsize <= MI_SMALL_SIZE_MAX)) {
+    mi_page_t* page = _mi_heap_get_free_small_page(heap, padsize);
+    const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0;
+    if (mi_likely(page->free != NULL && is_aligned))
+    {
+      #if MI_STAT>1
+      mi_heap_stat_increase(heap, malloc, size);
+      #endif
+      void* p = _mi_page_malloc(heap, page, padsize); // TODO: inline _mi_page_malloc
+      mi_assert_internal(p != NULL);
+      mi_assert_internal(((uintptr_t)p + offset) % alignment == 0);
+      if (zero) { _mi_block_zero_init(page, p, size); }
+      return p;
+    }
+  }
+  // fallback
+  return mi_heap_malloc_zero_aligned_at_fallback(heap, size, alignment, offset, zero);
+}
+
+
+// ------------------------------------------------------
+// Optimized mi_heap_malloc_aligned / mi_malloc_aligned
+// ------------------------------------------------------
 
 mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
   return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false);
 }
 
 mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept {
-  return mi_heap_malloc_aligned_at(heap, size, alignment, 0);
+  #if !MI_PADDING
+  // without padding, any small sized allocation is naturally aligned (see also `_mi_segment_page_start`)
+  if (!_mi_is_power_of_two(alignment)) return NULL;
+  if (mi_likely(_mi_is_power_of_two(size) && size >= alignment && size <= MI_SMALL_SIZE_MAX))
+  #else
+  // with padding, we can only guarantee this for fixed alignments
+  if (mi_likely((alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2)))
+                && size <= MI_SMALL_SIZE_MAX))
+  #endif
+  {
+    // fast path for common alignment and size
+    return mi_heap_malloc_small(heap, size);
+  }
+  else {
+    return mi_heap_malloc_aligned_at(heap, size, alignment, 0);
+  }
 }
 
+// ------------------------------------------------------
+// Aligned Allocation
+// ------------------------------------------------------
+
 mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
   return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true);
 }
@@ -113,6 +165,10 @@ mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t align
 }
 
 
+// ------------------------------------------------------
+// Aligned re-allocation
+// ------------------------------------------------------
+
 static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset, bool zero) mi_attr_noexcept {
   mi_assert(alignment > 0);
   if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero);
@@ -137,7 +193,7 @@ static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t ne
           memset((uint8_t*)newp + start, 0, newsize - start);
         }
       }
-      memcpy(newp, p, (newsize > size ? size : newsize));
+      _mi_memcpy_aligned(newp, p, (newsize > size ? size : newsize));
       mi_free(p); // only free if successful
     }
     return newp;
index c1c880ca2c30c67cfaba85528ac2de68f6090907..41d0a386e7e4bbdb2131f47110bd627788b3f614 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -17,69 +17,68 @@ terms of the MIT license. A copy of the license can be found in the file
 /* ------------------------------------------------------
    Override system malloc on macOS
    This is done through the malloc zone interface.
-   It seems we also need to interpose (see `alloc-override.c`)
-   or otherwise we get zone errors as there are usually 
-   already allocations done by the time we take over the 
-   zone. Unfortunately, that means we need to replace
-   the `free` with a checked free (`cfree`) impacting 
-   performance.
+   It seems to be most robust in combination with interposing
+   though or otherwise we may get zone errors as there are could
+   be allocations done by the time we take over the 
+   zone. 
 ------------------------------------------------------ */
 
 #include <AvailabilityMacros.h>
 #include <malloc/malloc.h>
 #include <string.h>  // memset
+#include <stdlib.h>
 
-#if defined(MAC_OS_X_VERSION_10_6) && \
-    MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
 // only available from OSX 10.6
 extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_import));
 #endif
 
-
 /* ------------------------------------------------------
    malloc zone members
 ------------------------------------------------------ */
 
 static size_t zone_size(malloc_zone_t* zone, const void* p) {
-  UNUSED(zone);
-  if (!mi_is_in_heap_region(p))
-    return 0; // not our pointer, bail out
-  
+  MI_UNUSED(zone);
+  if (!mi_is_in_heap_region(p)){ return 0; } // not our pointer, bail out
   return mi_usable_size(p);
 }
 
 static void* zone_malloc(malloc_zone_t* zone, size_t size) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_malloc(size);
 }
 
 static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_calloc(count, size);
 }
 
 static void* zone_valloc(malloc_zone_t* zone, size_t size) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_malloc_aligned(size, _mi_os_page_size());
 }
 
 static void zone_free(malloc_zone_t* zone, void* p) {
-  UNUSED(zone);
-  return mi_free(p);
+  MI_UNUSED(zone);
+  mi_cfree(p);
 }
 
 static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_realloc(p, newsize);
 }
 
 static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_malloc_aligned(size,alignment);
 }
 
 static void zone_destroy(malloc_zone_t* zone) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   // todo: ignore for now?
 }
 
@@ -100,16 +99,21 @@ static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) {
 }
 
 static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) {
-  UNUSED(zone); UNUSED(size);
+  MI_UNUSED(zone); MI_UNUSED(size);
   mi_collect(false);
   return 0;
 }
 
 static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) {
-  UNUSED(size);
+  MI_UNUSED(size);
   zone_free(zone,p);
 }
 
+static boolean_t zone_claimed_address(malloc_zone_t* zone, void* p) {
+  MI_UNUSED(zone);
+  return mi_is_in_heap_region(p);
+}
+
 
 /* ------------------------------------------------------
    Introspection members
@@ -121,43 +125,43 @@ static kern_return_t intro_enumerator(task_t task, void* p,
                             vm_range_recorder_t recorder)
 {
   // todo: enumerate all memory
-  UNUSED(task); UNUSED(p); UNUSED(type_mask); UNUSED(zone_address);
-  UNUSED(reader); UNUSED(recorder);
+  MI_UNUSED(task); MI_UNUSED(p); MI_UNUSED(type_mask); MI_UNUSED(zone_address);
+  MI_UNUSED(reader); MI_UNUSED(recorder);
   return KERN_SUCCESS;
 }
 
 static size_t intro_good_size(malloc_zone_t* zone, size_t size) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return mi_good_size(size);
 }
 
 static boolean_t intro_check(malloc_zone_t* zone) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return true;
 }
 
 static void intro_print(malloc_zone_t* zone, boolean_t verbose) {
-  UNUSED(zone); UNUSED(verbose);
+  MI_UNUSED(zone); MI_UNUSED(verbose);
   mi_stats_print(NULL);
 }
 
 static void intro_log(malloc_zone_t* zone, void* p) {
-  UNUSED(zone); UNUSED(p);
+  MI_UNUSED(zone); MI_UNUSED(p);
   // todo?
 }
 
 static void intro_force_lock(malloc_zone_t* zone) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   // todo?
 }
 
 static void intro_force_unlock(malloc_zone_t* zone) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   // todo?
 }
 
 static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   // todo...
   stats->blocks_in_use = 0;
   stats->size_in_use = 0;
@@ -166,7 +170,7 @@ static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
 }
 
 static boolean_t intro_zone_locked(malloc_zone_t* zone) {
-  UNUSED(zone);
+  MI_UNUSED(zone);
   return false;
 }
 
@@ -175,7 +179,228 @@ static boolean_t intro_zone_locked(malloc_zone_t* zone) {
   At process start, override the default allocator
 ------------------------------------------------------ */
 
-static malloc_zone_t* mi_get_default_zone()
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wc99-extensions"
+#endif
+
+static malloc_introspection_t mi_introspect = {
+  .enumerator = &intro_enumerator,
+  .good_size = &intro_good_size,
+  .check = &intro_check,
+  .print = &intro_print,
+  .log = &intro_log,
+  .force_lock = &intro_force_lock,
+  .force_unlock = &intro_force_unlock,
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+  .statistics = &intro_statistics,
+  .zone_locked = &intro_zone_locked,
+#endif
+};
+
+static malloc_zone_t mi_malloc_zone = {
+  // note: even with designators, the order is important for C++ compilation
+  //.reserved1 = NULL,
+  //.reserved2 = NULL,
+  .size = &zone_size,
+  .malloc = &zone_malloc,
+  .calloc = &zone_calloc,
+  .valloc = &zone_valloc,
+  .free = &zone_free,
+  .realloc = &zone_realloc,
+  .destroy = &zone_destroy,
+  .zone_name = "mimalloc",
+  .batch_malloc = &zone_batch_malloc,
+  .batch_free = &zone_batch_free,
+  .introspect = &mi_introspect,  
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+  #if defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
+  .version = 10,
+  #else
+  .version = 9,
+  #endif
+  // switch to version 9+ on OSX 10.6 to support memalign.
+  .memalign = &zone_memalign,
+  .free_definite_size = &zone_free_definite_size,
+  .pressure_relief = &zone_pressure_relief,
+  #if defined(MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)
+  .claimed_address = &zone_claimed_address,
+  #endif
+#else
+  .version = 4,
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined(MI_OSX_INTERPOSE) && defined(MI_SHARED_LIB_EXPORT)
+
+// ------------------------------------------------------
+// Override malloc_xxx and malloc_zone_xxx api's to use only 
+// our mimalloc zone. Since even the loader uses malloc
+// on macOS, this ensures that all allocations go through
+// mimalloc (as all calls are interposed).
+// The main `malloc`, `free`, etc calls are interposed in `alloc-override.c`,
+// Here, we also override macOS specific API's like
+// `malloc_zone_calloc` etc. see <https://github.com/aosm/libmalloc/blob/master/man/malloc_zone_malloc.3>
+// ------------------------------------------------------
+
+static inline malloc_zone_t* mi_get_default_zone(void)
+{
+  static bool init;
+  if (mi_unlikely(!init)) { 
+    init = true;
+    malloc_zone_register(&mi_malloc_zone);  // by calling register we avoid a zone error on free (see <http://eatmyrandom.blogspot.com/2010/03/mallocfree-interception-on-mac-os-x.html>)
+  }
+  return &mi_malloc_zone;
+}
+
+mi_decl_externc int  malloc_jumpstart(uintptr_t cookie);
+mi_decl_externc void _malloc_fork_prepare(void);
+mi_decl_externc void _malloc_fork_parent(void);
+mi_decl_externc void _malloc_fork_child(void);
+
+
+static malloc_zone_t* mi_malloc_create_zone(vm_size_t size, unsigned flags) {
+  MI_UNUSED(size); MI_UNUSED(flags);
+  return mi_get_default_zone();
+}
+
+static malloc_zone_t* mi_malloc_default_zone (void) {   
+  return mi_get_default_zone();
+}
+
+static malloc_zone_t* mi_malloc_default_purgeable_zone(void) {
+  return mi_get_default_zone();
+}
+
+static void mi_malloc_destroy_zone(malloc_zone_t* zone) {
+  MI_UNUSED(zone);
+  // nothing.
+}
+
+static kern_return_t mi_malloc_get_all_zones (task_t task, memory_reader_t mr, vm_address_t** addresses, unsigned* count) {
+  MI_UNUSED(task); MI_UNUSED(mr);
+  if (addresses != NULL) *addresses = NULL;
+  if (count != NULL) *count = 0;
+  return KERN_SUCCESS;
+}
+
+static const char* mi_malloc_get_zone_name(malloc_zone_t* zone) {  
+  return (zone == NULL ? mi_malloc_zone.zone_name : zone->zone_name);
+}
+
+static void mi_malloc_set_zone_name(malloc_zone_t* zone, const char* name) {  
+  MI_UNUSED(zone); MI_UNUSED(name);
+}
+
+static int mi_malloc_jumpstart(uintptr_t cookie) {
+  MI_UNUSED(cookie);
+  return 1; // or 0 for no error?
+}
+
+static void mi__malloc_fork_prepare(void) {
+  // nothing  
+}
+static void mi__malloc_fork_parent(void) {
+  // nothing
+}
+static void mi__malloc_fork_child(void) {
+  // nothing
+}
+
+static void mi_malloc_printf(const char* fmt, ...) {
+  MI_UNUSED(fmt);
+}
+
+static bool zone_check(malloc_zone_t* zone) {
+  MI_UNUSED(zone);
+  return true;
+}
+
+static malloc_zone_t* zone_from_ptr(const void* p) {
+  MI_UNUSED(p);
+  return mi_get_default_zone();
+}
+
+static void zone_log(malloc_zone_t* zone, void* p) {
+  MI_UNUSED(zone); MI_UNUSED(p);
+}
+
+static void zone_print(malloc_zone_t* zone, bool b) {
+  MI_UNUSED(zone); MI_UNUSED(b);
+}
+
+static void zone_print_ptr_info(void* p) {
+  MI_UNUSED(p);
+}
+
+static void zone_register(malloc_zone_t* zone) {
+  MI_UNUSED(zone);
+}
+
+static void zone_unregister(malloc_zone_t* zone) {
+  MI_UNUSED(zone);
+}
+
+// use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1`
+// See: <https://books.google.com/books?id=K8vUkpOXhN4C&pg=PA73>
+struct mi_interpose_s {
+  const void* replacement;
+  const void* target;
+};
+#define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun }
+#define MI_INTERPOSE_MI(fun)            MI_INTERPOSE_FUN(fun,mi_##fun)
+#define MI_INTERPOSE_ZONE(fun)          MI_INTERPOSE_FUN(malloc_##fun,fun)
+__attribute__((used)) static const struct mi_interpose_s _mi_zone_interposes[]  __attribute__((section("__DATA, __interpose"))) =
+{
+
+  MI_INTERPOSE_MI(malloc_create_zone),
+  MI_INTERPOSE_MI(malloc_default_purgeable_zone),
+  MI_INTERPOSE_MI(malloc_default_zone),
+  MI_INTERPOSE_MI(malloc_destroy_zone),
+  MI_INTERPOSE_MI(malloc_get_all_zones),
+  MI_INTERPOSE_MI(malloc_get_zone_name),
+  MI_INTERPOSE_MI(malloc_jumpstart),  
+  MI_INTERPOSE_MI(malloc_printf),
+  MI_INTERPOSE_MI(malloc_set_zone_name),
+  MI_INTERPOSE_MI(_malloc_fork_child),
+  MI_INTERPOSE_MI(_malloc_fork_parent),
+  MI_INTERPOSE_MI(_malloc_fork_prepare),
+  
+  MI_INTERPOSE_ZONE(zone_batch_free),
+  MI_INTERPOSE_ZONE(zone_batch_malloc),
+  MI_INTERPOSE_ZONE(zone_calloc),
+  MI_INTERPOSE_ZONE(zone_check),
+  MI_INTERPOSE_ZONE(zone_free),
+  MI_INTERPOSE_ZONE(zone_from_ptr),
+  MI_INTERPOSE_ZONE(zone_log),
+  MI_INTERPOSE_ZONE(zone_malloc),
+  MI_INTERPOSE_ZONE(zone_memalign),
+  MI_INTERPOSE_ZONE(zone_print),
+  MI_INTERPOSE_ZONE(zone_print_ptr_info),
+  MI_INTERPOSE_ZONE(zone_realloc),
+  MI_INTERPOSE_ZONE(zone_register),
+  MI_INTERPOSE_ZONE(zone_unregister),
+  MI_INTERPOSE_ZONE(zone_valloc)
+};
+
+
+#else
+
+// ------------------------------------------------------
+// hook into the zone api's without interposing
+// This is the official way of adding an allocator but
+// it seems less robust than using interpose.
+// ------------------------------------------------------
+
+static inline malloc_zone_t* mi_get_default_zone(void)
 {
   // The first returned zone is the real default
   malloc_zone_t** zones = NULL;
@@ -190,63 +415,35 @@ static malloc_zone_t* mi_get_default_zone()
   }
 }
 
-static void __attribute__((constructor)) _mi_macos_override_malloc()
-{
-  static malloc_introspection_t intro;
-  memset(&intro, 0, sizeof(intro));
-
-  intro.enumerator = &intro_enumerator;
-  intro.good_size = &intro_good_size;
-  intro.check = &intro_check;
-  intro.print = &intro_print;
-  intro.log = &intro_log;
-  intro.force_lock = &intro_force_lock;
-  intro.force_unlock = &intro_force_unlock;
-
-  static malloc_zone_t zone;
-  memset(&zone, 0, sizeof(zone));
-
-  zone.version = 4;
-  zone.zone_name = "mimalloc";
-  zone.size = &zone_size;
-  zone.introspect = &intro;
-  zone.malloc = &zone_malloc;
-  zone.calloc = &zone_calloc;
-  zone.valloc = &zone_valloc;
-  zone.free = &zone_free;
-  zone.realloc = &zone_realloc;
-  zone.destroy = &zone_destroy;
-  zone.batch_malloc = &zone_batch_malloc;
-  zone.batch_free = &zone_batch_free;
-
+#if defined(__clang__)
+__attribute__((constructor(0))) 
+#else
+__attribute__((constructor))      // seems not supported by g++-11 on the M1
+#endif
+static void _mi_macos_override_malloc() {
   malloc_zone_t* purgeable_zone = NULL;
 
-#if defined(MAC_OS_X_VERSION_10_6) && \
-    MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-  // switch to version 9 on OSX 10.6 to support memalign.
-  zone.version = 9;
-  zone.memalign = &zone_memalign;
-  zone.free_definite_size = &zone_free_definite_size;
-  zone.pressure_relief = &zone_pressure_relief;
-  intro.zone_locked = &intro_zone_locked;
-  intro.statistics = &intro_statistics;
-
+  #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
   // force the purgeable zone to exist to avoid strange bugs
   if (malloc_default_purgeable_zone) {
     purgeable_zone = malloc_default_purgeable_zone();
   }
-#endif
-
-  // Register our zone
-  malloc_zone_register(&zone);
+  #endif
 
+  // Register our zone.
+  // thomcc: I think this is still needed to put us in the zone list.
+  malloc_zone_register(&mi_malloc_zone);
   // Unregister the default zone, this makes our zone the new default
   // as that was the last registered.
   malloc_zone_t *default_zone = mi_get_default_zone();
-  malloc_zone_unregister(default_zone);
+  // thomcc: Unsure if the next test is *always* false or just false in the
+  // cases I've tried. I'm also unsure if the code inside is needed. at all
+  if (default_zone != &mi_malloc_zone) {
+    malloc_zone_unregister(default_zone);
 
-  // Reregister the default zone so free and realloc in that zone keep working.
-  malloc_zone_register(default_zone);
+    // Reregister the default zone so free and realloc in that zone keep working.
+    malloc_zone_register(default_zone);
+  }
 
   // Unregister, and re-register the purgeable_zone to avoid bugs if it occurs
   // earlier than the default zone.
@@ -256,5 +453,6 @@ static void __attribute__((constructor)) _mi_macos_override_malloc()
   }
 
 }
+#endif  // MI_OSX_INTERPOSE
 
 #endif // MI_MALLOC_OVERRIDE
index ae7ad7ddb8f48fbbc94f492249b2d4945469f6d3..e29cb4b231194d727834c6962a268b81fff80c13 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -13,18 +13,29 @@ terms of the MIT license. A copy of the license can be found in the file
 #error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)"
 #endif
 
-#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) // || (defined(__MACH__) && !defined(MI_INTERPOSE)))
+#if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) 
+
+#if defined(__APPLE__)
+#include <AvailabilityMacros.h>
+mi_decl_externc void   vfree(void* p);
+mi_decl_externc size_t malloc_size(const void* p);
+mi_decl_externc size_t malloc_good_size(size_t size);
+#endif
+
+// helper definition for C override of C++ new
+typedef struct mi_nothrow_s { int _tag; } mi_nothrow_t;
 
 // ------------------------------------------------------
 // Override system malloc
 // ------------------------------------------------------
 
-#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__)
-  // use aliasing to alias the exported function to one of our `mi_` functions
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__) && !defined(MI_VALGRIND)
+  // gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions
   #if (defined(__GNUC__) && __GNUC__ >= 9)
-    #define MI_FORWARD(fun)      __attribute__((alias(#fun), used, visibility("default"), copy(fun)))
+    #pragma GCC diagnostic ignored "-Wattributes"  // or we get warnings that nodiscard is ignored on a forward
+    #define MI_FORWARD(fun)      __attribute__((alias(#fun), used, visibility("default"), copy(fun)));
   #else
-    #define MI_FORWARD(fun)      __attribute__((alias(#fun), used, visibility("default")))
+    #define MI_FORWARD(fun)      __attribute__((alias(#fun), used, visibility("default")));
   #endif
   #define MI_FORWARD1(fun,x)      MI_FORWARD(fun)
   #define MI_FORWARD2(fun,x,y)    MI_FORWARD(fun)
@@ -32,7 +43,7 @@ terms of the MIT license. A copy of the license can be found in the file
   #define MI_FORWARD0(fun,x)      MI_FORWARD(fun)
   #define MI_FORWARD02(fun,x,y)   MI_FORWARD(fun)
 #else
-  // use forwarding by calling our `mi_` function
+  // otherwise use forwarding by calling our `mi_` function 
   #define MI_FORWARD1(fun,x)      { return fun(x); }
   #define MI_FORWARD2(fun,x,y)    { return fun(x,y); }
   #define MI_FORWARD3(fun,x,y,z)  { return fun(x,y,z); }
@@ -40,7 +51,11 @@ terms of the MIT license. A copy of the license can be found in the file
   #define MI_FORWARD02(fun,x,y)   { fun(x,y); }
 #endif
 
-#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_INTERPOSE)
+#if defined(__APPLE__) && defined(MI_SHARED_LIB_EXPORT) && defined(MI_OSX_INTERPOSE)    
+  // define MI_OSX_IS_INTERPOSED as we should not provide forwarding definitions for 
+  // functions that are interposed (or the interposing does not work)
+  #define MI_OSX_IS_INTERPOSED
+
   // use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1`
   // See: <https://books.google.com/books?id=K8vUkpOXhN4C&pg=PA73>
   struct mi_interpose_s {
@@ -49,6 +64,7 @@ terms of the MIT license. A copy of the license can be found in the file
   };
   #define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun }
   #define MI_INTERPOSE_MI(fun)            MI_INTERPOSE_FUN(fun,mi_##fun)
+  
   __attribute__((used)) static struct mi_interpose_s _mi_interposes[]  __attribute__((section("__DATA, __interpose"))) =
   {
     MI_INTERPOSE_MI(malloc),
@@ -60,21 +76,60 @@ terms of the MIT license. A copy of the license can be found in the file
     MI_INTERPOSE_MI(posix_memalign),
     MI_INTERPOSE_MI(reallocf),
     MI_INTERPOSE_MI(valloc),
-    // some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity <https://github.com/nneonneo/osx-10.9-opensource/blob/master/objc4-551.1/runtime/hashtable2.mm>)
+    MI_INTERPOSE_MI(malloc_size),
+    MI_INTERPOSE_MI(malloc_good_size),
+    #if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 
+    MI_INTERPOSE_MI(aligned_alloc),
+    #endif
+    #ifdef MI_OSX_ZONE
+    // we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely
+    MI_INTERPOSE_MI(free),
+    MI_INTERPOSE_FUN(vfree,mi_free),
+    #else
+    // sometimes code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity <https://github.com/nneonneo/osx-10.9-opensource/blob/master/objc4-551.1/runtime/hashtable2.mm>)
     MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us
+    MI_INTERPOSE_FUN(vfree,mi_cfree),
+    #endif
+  };
+
+  #ifdef __cplusplus
+  extern "C" {
+  #endif
+  void  _ZdlPv(void* p);   // delete
+  void  _ZdaPv(void* p);   // delete[]
+  void  _ZdlPvm(void* p, size_t n);  // delete
+  void  _ZdaPvm(void* p, size_t n);  // delete[]
+  void* _Znwm(size_t n);  // new
+  void* _Znam(size_t n);  // new[]
+  void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new nothrow
+  void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag); // new[] nothrow
+  #ifdef __cplusplus
+  }
+  #endif
+  __attribute__((used)) static struct mi_interpose_s _mi_cxx_interposes[]  __attribute__((section("__DATA, __interpose"))) =
+  {
+    MI_INTERPOSE_FUN(_ZdlPv,mi_free),
+    MI_INTERPOSE_FUN(_ZdaPv,mi_free),
+    MI_INTERPOSE_FUN(_ZdlPvm,mi_free_size),
+    MI_INTERPOSE_FUN(_ZdaPvm,mi_free_size),
+    MI_INTERPOSE_FUN(_Znwm,mi_new),
+    MI_INTERPOSE_FUN(_Znam,mi_new),
+    MI_INTERPOSE_FUN(_ZnwmRKSt9nothrow_t,mi_new_nothrow),
+    MI_INTERPOSE_FUN(_ZnamRKSt9nothrow_t,mi_new_nothrow),
   };
+
 #elif defined(_MSC_VER)
   // cannot override malloc unless using a dll.
   // we just override new/delete which does work in a static library.
 #else
-  // On all other systems forward to our API
-  void* malloc(size_t size)              MI_FORWARD1(mi_malloc, size);
-  void* calloc(size_t size, size_t n)    MI_FORWARD2(mi_calloc, size, n);
-  void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize);
-  void  free(void* p)                    MI_FORWARD0(mi_free, p);
+  // On all other systems forward to our API  
+  void* malloc(size_t size)              MI_FORWARD1(mi_malloc, size)
+  void* calloc(size_t size, size_t n)    MI_FORWARD2(mi_calloc, size, n)
+  void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize)
+  void  free(void* p)                    MI_FORWARD0(mi_free, p)
 #endif
 
-#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__)
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__)
 #pragma GCC visibility push(default)
 #endif
 
@@ -89,18 +144,21 @@ terms of the MIT license. A copy of the license can be found in the file
   // see <https://en.cppreference.com/w/cpp/memory/new/operator_new>
   // ------------------------------------------------------
   #include <new>
-  void operator delete(void* p) noexcept              MI_FORWARD0(mi_free,p);
-  void operator delete[](void* p) noexcept            MI_FORWARD0(mi_free,p);
 
-  void* operator new(std::size_t n) noexcept(false)   MI_FORWARD1(mi_new,n);
-  void* operator new[](std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n);
+  #ifndef MI_OSX_IS_INTERPOSED
+    void operator delete(void* p) noexcept              MI_FORWARD0(mi_free,p)
+    void operator delete[](void* p) noexcept            MI_FORWARD0(mi_free,p)
+
+    void* operator new(std::size_t n) noexcept(false)   MI_FORWARD1(mi_new,n)
+    void* operator new[](std::size_t n) noexcept(false) MI_FORWARD1(mi_new,n)
 
-  void* operator new  (std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); }
-  void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); }
+    void* operator new  (std::size_t n, const std::nothrow_t& tag) noexcept { MI_UNUSED(tag); return mi_new_nothrow(n); }
+    void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { MI_UNUSED(tag); return mi_new_nothrow(n); }
 
-  #if (__cplusplus >= 201402L || _MSC_VER >= 1916)
-  void operator delete  (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n);
-  void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n);
+    #if (__cplusplus >= 201402L || _MSC_VER >= 1916)
+    void operator delete  (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n)
+    void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n)
+    #endif
   #endif
 
   #if (__cplusplus > 201402L && defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5))
@@ -108,98 +166,107 @@ terms of the MIT license. A copy of the license can be found in the file
   void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
   void operator delete  (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
   void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
-
+  void operator delete  (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
+  void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
+  
   void* operator new( std::size_t n, std::align_val_t al)   noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
   void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); }
   void* operator new  (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
   void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
   #endif
 
-#elif (defined(__GNUC__) || defined(__clang__))
+#elif (defined(__GNUC__) || defined(__clang__)) 
   // ------------------------------------------------------
   // Override by defining the mangled C++ names of the operators (as
   // used by GCC and CLang).
   // See <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling>
   // ------------------------------------------------------
-  void _ZdlPv(void* p)            MI_FORWARD0(mi_free,p); // delete
-  void _ZdaPv(void* p)            MI_FORWARD0(mi_free,p); // delete[]
-  void _ZdlPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n);
-  void _ZdaPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n);
+  
+  void _ZdlPv(void* p)            MI_FORWARD0(mi_free,p) // delete
+  void _ZdaPv(void* p)            MI_FORWARD0(mi_free,p) // delete[]
+  void _ZdlPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n)
+  void _ZdaPvm(void* p, size_t n) MI_FORWARD02(mi_free_size,p,n)
   void _ZdlPvSt11align_val_t(void* p, size_t al)            { mi_free_aligned(p,al); }
   void _ZdaPvSt11align_val_t(void* p, size_t al)            { mi_free_aligned(p,al); }
   void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); }
   void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t al) { mi_free_size_aligned(p,n,al); }
-
-  typedef struct mi_nothrow_s {  } mi_nothrow_t;
+  
   #if (MI_INTPTR_SIZE==8)
-    void* _Znwm(size_t n)                             MI_FORWARD1(mi_new,n);  // new 64-bit
-    void* _Znam(size_t n)                             MI_FORWARD1(mi_new,n);  // new[] 64-bit
-    void* _ZnwmSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al);
-    void* _ZnamSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al);
-    void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); }
-    void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); }
-    void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
-    void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+    void* _Znwm(size_t n)                             MI_FORWARD1(mi_new,n)  // new 64-bit
+    void* _Znam(size_t n)                             MI_FORWARD1(mi_new,n)  // new[] 64-bit
+    void* _ZnwmRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
+    void* _ZnamRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }     
+    void* _ZnwmSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al)
+    void* _ZnamSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al)
+    void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+    void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
   #elif (MI_INTPTR_SIZE==4)
-    void* _Znwj(size_t n)                             MI_FORWARD1(mi_new,n);  // new 64-bit
-    void* _Znaj(size_t n)                             MI_FORWARD1(mi_new,n);  // new[] 64-bit
-    void* _ZnwjSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al);
-    void* _ZnajSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al);
-    void* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); }
-    void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { UNUSED(tag); return mi_new_nothrow(n); }
-    void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
-    void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+    void* _Znwj(size_t n)                             MI_FORWARD1(mi_new,n)  // new 64-bit
+    void* _Znaj(size_t n)                             MI_FORWARD1(mi_new,n)  // new[] 64-bit
+    void* _ZnwjRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }
+    void* _ZnajRKSt9nothrow_t(size_t n, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_nothrow(n); }   
+    void* _ZnwjSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al)
+    void* _ZnajSt11align_val_t(size_t n, size_t al)   MI_FORWARD2(mi_new_aligned, n, al)
+    void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
+    void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t n, size_t al, mi_nothrow_t tag) { MI_UNUSED(tag); return mi_new_aligned_nothrow(n,al); }
   #else
-  #error "define overloads for new/delete for this platform (just for performance, can be skipped)"
+    #error "define overloads for new/delete for this platform (just for performance, can be skipped)"
   #endif
 #endif // __cplusplus
 
+// ------------------------------------------------------
+// Further Posix & Unix functions definitions
+// ------------------------------------------------------
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-// ------------------------------------------------------
-// Posix & Unix functions definitions
-// ------------------------------------------------------
+#ifndef MI_OSX_IS_INTERPOSED
+  // Forward Posix/Unix calls as well
+  void*  reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize)
+  size_t malloc_size(const void* p)        MI_FORWARD1(mi_usable_size,p)
+  #if !defined(__ANDROID__) && !defined(__FreeBSD__)
+  size_t malloc_usable_size(void *p)       MI_FORWARD1(mi_usable_size,p)
+  #else
+  size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p)
+  #endif
 
-void   cfree(void* p)                    MI_FORWARD0(mi_free, p);
-void*  reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize);
-size_t malloc_size(const void* p)        MI_FORWARD1(mi_usable_size,p);
-#if !defined(__ANDROID__)
-size_t malloc_usable_size(void *p)       MI_FORWARD1(mi_usable_size,p);
-#else
-size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p);
+  // No forwarding here due to aliasing/name mangling issues
+  void*  valloc(size_t size)               { return mi_valloc(size); }
+  void   vfree(void* p)                    { mi_free(p); }                
+  size_t malloc_good_size(size_t size)     { return mi_malloc_good_size(size); }
+  int    posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); }
+  
+  // `aligned_alloc` is only available when __USE_ISOC11 is defined.
+  // Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot
+  // override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9.
+  // Fortunately, in the case where `aligned_alloc` is declared as `static inline` it
+  // uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we  can avoid overriding it ourselves.
+  #if __USE_ISOC11 
+  void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
+  #endif
 #endif
 
 // no forwarding here due to aliasing/name mangling issues
-void* valloc(size_t size)                                     { return mi_valloc(size); }
-void* pvalloc(size_t size)                                    { return mi_pvalloc(size); }
-void* reallocarray(void* p, size_t count, size_t size)        { return mi_reallocarray(p, count, size); }
-void* memalign(size_t alignment, size_t size)                 { return mi_memalign(alignment, size); }
-int   posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); }
-void* _aligned_malloc(size_t alignment, size_t size)          { return mi_aligned_alloc(alignment, size); }
-
-// on some glibc `aligned_alloc` is declared `static inline` so we cannot override it (e.g. Conda). This happens
-// when _GLIBCXX_HAVE_ALIGNED_ALLOC is not defined. However, in those cases it will use `memalign`, `posix_memalign`, 
-// or `_aligned_malloc` and we can avoid overriding it ourselves.
-// We should always override if using C compilation. (issue #276)
-#if _GLIBCXX_HAVE_ALIGNED_ALLOC || !defined(__cplusplus)
-void* aligned_alloc(size_t alignment, size_t size)   { return mi_aligned_alloc(alignment, size); }
-#endif
-
+void  cfree(void* p)                                    { mi_free(p); } 
+void* pvalloc(size_t size)                              { return mi_pvalloc(size); }
+void* reallocarray(void* p, size_t count, size_t size)  { return mi_reallocarray(p, count, size); }
+int   reallocarr(void* p, size_t count, size_t size)    { return mi_reallocarr(p, count, size); }
+void* memalign(size_t alignment, size_t size)           { return mi_memalign(alignment, size); }
+void* _aligned_malloc(size_t alignment, size_t size)    { return mi_aligned_alloc(alignment, size); }
 
 #if defined(__GLIBC__) && defined(__linux__)
   // forward __libc interface (needed for glibc-based Linux distributions)
-  void* __libc_malloc(size_t size)                  MI_FORWARD1(mi_malloc,size);
-  void* __libc_calloc(size_t count, size_t size)    MI_FORWARD2(mi_calloc,count,size);
-  void* __libc_realloc(void* p, size_t size)        MI_FORWARD2(mi_realloc,p,size);
-  void  __libc_free(void* p)                        MI_FORWARD0(mi_free,p);
-  void  __libc_cfree(void* p)                       MI_FORWARD0(mi_free,p);
-
-  void* __libc_valloc(size_t size)                                { return mi_valloc(size); }
-  void* __libc_pvalloc(size_t size)                               { return mi_pvalloc(size); }
-  void* __libc_memalign(size_t alignment, size_t size)            { return mi_memalign(alignment,size); }
+  void* __libc_malloc(size_t size)                      MI_FORWARD1(mi_malloc,size)
+  void* __libc_calloc(size_t count, size_t size)        MI_FORWARD2(mi_calloc,count,size)
+  void* __libc_realloc(void* p, size_t size)            MI_FORWARD2(mi_realloc,p,size)
+  void  __libc_free(void* p)                            MI_FORWARD0(mi_free,p)
+  void  __libc_cfree(void* p)                           MI_FORWARD0(mi_free,p)
+
+  void* __libc_valloc(size_t size)                      { return mi_valloc(size); }
+  void* __libc_pvalloc(size_t size)                     { return mi_pvalloc(size); }
+  void* __libc_memalign(size_t alignment, size_t size)  { return mi_memalign(alignment,size); }
   int   __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); }
 #endif
 
@@ -207,7 +274,7 @@ void* aligned_alloc(size_t alignment, size_t size)   { return mi_aligned_alloc(a
 }
 #endif
 
-#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__)
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__APPLE__)
 #pragma GCC visibility pop
 #endif
 
index 4395893b62d9ece1c685f47ff93cf35b7e0b583d..176e7ec3070f18df0dae8ed8ee5a5954ca7cd3f3 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018,2019, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -17,9 +17,13 @@ terms of the MIT license. A copy of the license can be found in the file
 // ------------------------------------------------------
 
 #include <errno.h>
-#include <string.h>  // memcpy
+#include <string.h>  // memset
 #include <stdlib.h>  // getenv
 
+#ifdef _MSC_VER
+#pragma warning(disable:4996)  // getenv _wgetenv
+#endif
+
 #ifndef EINVAL
 #define EINVAL 22
 #endif
@@ -28,14 +32,20 @@ terms of the MIT license. A copy of the license can be found in the file
 #endif
 
 
-size_t mi_malloc_size(const void* p) mi_attr_noexcept {
+mi_decl_nodiscard size_t mi_malloc_size(const void* p) mi_attr_noexcept {
+  //if (!mi_is_in_heap_region(p)) return 0;
   return mi_usable_size(p);
 }
 
-size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept {
+mi_decl_nodiscard size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept {
+  //if (!mi_is_in_heap_region(p)) return 0;
   return mi_usable_size(p);
 }
 
+mi_decl_nodiscard size_t mi_malloc_good_size(size_t size) mi_attr_noexcept {
+  return mi_good_size(size);
+}
+
 void mi_cfree(void* p) mi_attr_noexcept {
   if (mi_is_in_heap_region(p)) {
     mi_free(p);
@@ -46,73 +56,90 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept
   // Note: The spec dictates we should not modify `*p` on an error. (issue#27)
   // <http://man7.org/linux/man-pages/man3/posix_memalign.3.html>
   if (p == NULL) return EINVAL;
-  if (alignment % sizeof(void*) != 0) return EINVAL;   // natural alignment
-  if (!_mi_is_power_of_two(alignment)) return EINVAL;  // not a power of 2
-  void* q = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
+  if (alignment % sizeof(void*) != 0) return EINVAL;                   // natural alignment
+  if (alignment==0 || !_mi_is_power_of_two(alignment)) return EINVAL;  // not a power of 2
+  void* q = mi_malloc_aligned(size, alignment);
   if (q==NULL && size != 0) return ENOMEM;
   mi_assert_internal(((uintptr_t)q % alignment) == 0);
   *p = q;
   return 0;
 }
 
-mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept {
-  void* p = (mi_malloc_satisfies_alignment(alignment,size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
+mi_decl_nodiscard mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept {
+  void* p = mi_malloc_aligned(size, alignment);
   mi_assert_internal(((uintptr_t)p % alignment) == 0);
   return p;
 }
 
-mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept {
+mi_decl_nodiscard mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept {
   return mi_memalign( _mi_os_page_size(), size );
 }
 
-mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept {
+mi_decl_nodiscard mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept {
   size_t psize = _mi_os_page_size();
   if (size >= SIZE_MAX - psize) return NULL; // overflow
   size_t asize = _mi_align_up(size, psize);
   return mi_malloc_aligned(asize, psize);
 }
 
-mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept {
-  if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; 
-  if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see <https://en.cppreference.com/w/c/memory/aligned_alloc>
-  void* p = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
+mi_decl_nodiscard mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept {
+  if (mi_unlikely((size&(alignment-1)) != 0)) { // C11 requires alignment>0 && integral multiple, see <https://en.cppreference.com/w/c/memory/aligned_alloc>
+    #if MI_DEBUG > 0
+    _mi_error_message(EOVERFLOW, "(mi_)aligned_alloc requires the size to be an integral multiple of the alignment (size %zu, alignment %zu)\n", size, alignment);
+    #endif
+    return NULL;
+  }
+  // C11 also requires alignment to be a power-of-two which is checked in mi_malloc_aligned
+  void* p = mi_malloc_aligned(size, alignment);
   mi_assert_internal(((uintptr_t)p % alignment) == 0);
   return p;
 }
 
-void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept {  // BSD
+mi_decl_nodiscard void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept {  // BSD
   void* newp = mi_reallocn(p,count,size);
-  if (newp==NULL) errno = ENOMEM;
+  if (newp==NULL) { errno = ENOMEM; }
   return newp;
 }
 
+mi_decl_nodiscard int mi_reallocarr( void* p, size_t count, size_t size ) mi_attr_noexcept { // NetBSD
+  mi_assert(p != NULL);
+  if (p == NULL) {
+    errno = EINVAL;
+    return EINVAL;
+  }
+  void** op = (void**)p;  
+  void* newp = mi_reallocarray(*op, count, size);
+  if (mi_unlikely(newp == NULL)) return errno;
+  *op = newp;
+  return 0;
+}
+
 void* mi__expand(void* p, size_t newsize) mi_attr_noexcept {  // Microsoft
   void* res = mi_expand(p, newsize);
-  if (res == NULL) errno = ENOMEM;
+  if (res == NULL) { errno = ENOMEM; }
   return res;
 }
 
-mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
+mi_decl_nodiscard mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
   if (s==NULL) return NULL;
   size_t len;
   for(len = 0; s[len] != 0; len++) { }
   size_t size = (len+1)*sizeof(unsigned short);
   unsigned short* p = (unsigned short*)mi_malloc(size);
   if (p != NULL) {
-    memcpy(p,s,size);
+    _mi_memcpy(p,s,size);
   }
   return p;
 }
 
-mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s)  mi_attr_noexcept {
+mi_decl_nodiscard mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s)  mi_attr_noexcept {
   return (unsigned char*)mi_strdup((const char*)s);
 }
 
 int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept {
   if (buf==NULL || name==NULL) return EINVAL;
   if (size != NULL) *size = 0;
-  #pragma warning(suppress:4996)
-  char* p = getenv(name);
+  char* p = getenv(name);        // mscver warning 4996
   if (p==NULL) {
     *buf = NULL;
   }
@@ -132,8 +159,7 @@ int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name)
   *buf = NULL;
   return EINVAL;
 #else
-  #pragma warning(suppress:4996)
-  unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name);
+  unsigned short* p = (unsigned short*)_wgetenv((const wchar_t*)name);  // msvc warning 4996
   if (p==NULL) {
     *buf = NULL;
   }
@@ -146,10 +172,10 @@ int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name)
 #endif
 }
 
-void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft
+mi_decl_nodiscard void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { // Microsoft
   return mi_recalloc_aligned_at(p, newcount, size, alignment, offset);
 }
 
-void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft
+mi_decl_nodiscard void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { // Microsoft
   return mi_recalloc_aligned(p, newcount, size, alignment);
 }
index 5703452269ff4ed70cda99461435bc4bdbde6188..1a36b5da8a6193730bdd9ae28aebde90a931d08e 100644 (file)
@@ -1,14 +1,18 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
 -----------------------------------------------------------------------------*/
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE   // for realpath() on Linux
+#endif
+
 #include "mimalloc.h"
 #include "mimalloc-internal.h"
 #include "mimalloc-atomic.h"
 
-#include <string.h>  // memset, memcpy, strlen
+#include <string.h>  // memset, strlen
 #include <stdlib.h>  // malloc, exit
 
 #define MI_IN_ALLOC_C
@@ -23,27 +27,34 @@ terms of the MIT license. A copy of the license can be found in the file
 // Fall back to generic allocation only if the list is empty.
 extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept {
   mi_assert_internal(page->xblock_size==0||mi_page_block_size(page) >= size);
-  mi_block_t* block = page->free;
+  mi_block_t* const block = page->free;
   if (mi_unlikely(block == NULL)) {
     return _mi_malloc_generic(heap, size); 
   }
   mi_assert_internal(block != NULL && _mi_ptr_page(block) == page);
   // pop from the free list
-  page->free = mi_block_next(page, block);
   page->used++;
+  page->free = mi_block_next(page, block);
   mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page);
+
 #if (MI_DEBUG>0)
   if (!page->is_zero) { memset(block, MI_DEBUG_UNINIT, size); }
 #elif (MI_SECURE!=0)
   block->next = 0;  // don't leak internal data
 #endif
-#if (MI_STAT>1)
+
+#if (MI_STAT>0)
   const size_t bsize = mi_page_usable_block_size(page);
-  if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
+  if (bsize <= MI_MEDIUM_OBJ_SIZE_MAX) {
+    mi_heap_stat_increase(heap, normal, bsize);
+    mi_heap_stat_counter_increase(heap, normal_count, 1);
+#if (MI_STAT>1)
     const size_t bin = _mi_bin(bsize);
-    mi_heap_stat_increase(heap, normal[bin], 1);
+    mi_heap_stat_increase(heap, normal_bins[bin], 1);
+#endif
   }
 #endif
+
 #if (MI_PADDING > 0) && defined(MI_ENCODE_FREELIST)
   mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
   ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
@@ -54,6 +65,7 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
   const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes
   for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; }
 #endif
+
   return block;
 }
 
@@ -111,7 +123,7 @@ extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept {
 void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size) {
   // note: we need to initialize the whole usable block size to zero, not just the requested size,
   // or the recalloc/rezalloc functions cannot safely expand in place (see issue #63)
-  UNUSED(size);
+  MI_UNUSED(size);
   mi_assert_internal(p != NULL);
   mi_assert_internal(mi_usable_size(p) >= size); // size can be zero
   mi_assert_internal(_mi_ptr_page(p)==page);
@@ -135,7 +147,7 @@ mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept {
   return p;
 }
 
-void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) {
+void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept {
   void* p = mi_heap_malloc(heap,size);
   if (zero && p != NULL) {
     _mi_block_zero_init(_mi_ptr_page(p),p,size);  // todo: can we avoid getting the page again?
@@ -193,8 +205,8 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
 }
 #else
 static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block_t* block) {
-  UNUSED(page);
-  UNUSED(block);
+  MI_UNUSED(page);
+  MI_UNUSED(block);
   return false;
 }
 #endif
@@ -266,19 +278,68 @@ static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, co
 }
 #else
 static void mi_check_padding(const mi_page_t* page, const mi_block_t* block) {
-  UNUSED(page);
-  UNUSED(block);
+  MI_UNUSED(page);
+  MI_UNUSED(block);
 }
 
 static size_t mi_page_usable_size_of(const mi_page_t* page, const mi_block_t* block) {
-  UNUSED(block);
+  MI_UNUSED(block);
   return mi_page_usable_block_size(page);
 }
 
 static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size) {
-  UNUSED(page);
-  UNUSED(block);
-  UNUSED(min_size);
+  MI_UNUSED(page);
+  MI_UNUSED(block);
+  MI_UNUSED(min_size);
+}
+#endif
+
+// only maintain stats for smaller objects if requested
+#if (MI_STAT>0)
+static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
+  #if (MI_STAT < 2)  
+  MI_UNUSED(block);
+  #endif
+  mi_heap_t* const heap = mi_heap_get_default();
+  const size_t bsize = mi_page_usable_block_size(page);
+  #if (MI_STAT>1)
+  const size_t usize = mi_page_usable_size_of(page, block);
+  mi_heap_stat_decrease(heap, malloc, usize);
+  #endif  
+  if (bsize <= MI_MEDIUM_OBJ_SIZE_MAX) {
+    mi_heap_stat_decrease(heap, normal, bsize);
+    #if (MI_STAT > 1)
+    mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], 1);
+    #endif
+  }
+  else if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
+    mi_heap_stat_decrease(heap, large, bsize);
+  }
+  else {
+    mi_heap_stat_decrease(heap, huge, bsize);
+  }
+}
+#else
+static void mi_stat_free(const mi_page_t* page, const mi_block_t* block) {
+  MI_UNUSED(page); MI_UNUSED(block);
+}
+#endif
+
+#if (MI_STAT>0)
+// maintain stats for huge objects
+static void mi_stat_huge_free(const mi_page_t* page) {
+  mi_heap_t* const heap = mi_heap_get_default();
+  const size_t bsize = mi_page_block_size(page); // to match stats in `page.c:mi_page_huge_alloc`
+  if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
+    mi_heap_stat_decrease(heap, large, bsize);
+  }
+  else {
+    mi_heap_stat_decrease(heap, huge, bsize);
+  }
+}
+#else
+static void mi_stat_huge_free(const mi_page_t* page) {
+  MI_UNUSED(page);
 }
 #endif
 
@@ -298,18 +359,18 @@ static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* bloc
   #endif
 
   // huge page segments are always abandoned and can be freed immediately
-  mi_segment_t* const segment = _mi_page_segment(page);
-  if (segment->page_kind==MI_PAGE_HUGE) {
+  mi_segment_t* segment = _mi_page_segment(page);
+  if (segment->kind==MI_SEGMENT_HUGE) {
+    mi_stat_huge_free(page);
     _mi_segment_huge_page_free(segment, page, block);
     return;
   }
 
   // Try to put the block on either the page-local thread free list, or the heap delayed free list.
-  mi_thread_free_t tfree;
   mi_thread_free_t tfreex;
   bool use_delayed;
+  mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free);
   do {
-    tfree = mi_atomic_read_relaxed(&page->xthread_free);
     use_delayed = (mi_tf_delayed(tfree) == MI_USE_DELAYED_FREE);
     if (mi_unlikely(use_delayed)) {
       // unlikely: this only happens on the first concurrent free in a page that is in the full list
@@ -320,31 +381,30 @@ static mi_decl_noinline void _mi_free_block_mt(mi_page_t* page, mi_block_t* bloc
       mi_block_set_next(page, block, mi_tf_block(tfree));
       tfreex = mi_tf_set_block(tfree,block);
     }
-  } while (!mi_atomic_cas_weak(&page->xthread_free, tfreex, tfree));
+  } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex));
 
   if (mi_unlikely(use_delayed)) {
     // racy read on `heap`, but ok because MI_DELAYED_FREEING is set (see `mi_heap_delete` and `mi_heap_collect_abandon`)
-    mi_heap_t* const heap = mi_page_heap(page);
+    mi_heap_t* const heap = (mi_heap_t*)(mi_atomic_load_acquire(&page->xheap)); //mi_page_heap(page);
     mi_assert_internal(heap != NULL);
     if (heap != NULL) {
       // add to the delayed free list of this heap. (do this atomically as the lock only protects heap memory validity)
-      mi_block_t* dfree;
+      mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free);
       do {
-        dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
         mi_block_set_nextx(heap,block,dfree, heap->keys);
-      } while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
+      } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block));
     }
 
     // and reset the MI_DELAYED_FREEING flag
+    tfree = mi_atomic_load_relaxed(&page->xthread_free);
     do {
-      tfreex = tfree = mi_atomic_read_relaxed(&page->xthread_free);
+      tfreex = tfree;
       mi_assert_internal(mi_tf_delayed(tfree) == MI_DELAYED_FREEING);
       tfreex = mi_tf_set_delayed(tfree,MI_NO_DELAYED_FREE);
-    } while (!mi_atomic_cas_weak(&page->xthread_free, tfreex, tfree));
+    } while (!mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex));
   }
 }
 
-
 // regular free
 static inline void _mi_free_block(mi_page_t* page, bool local, mi_block_t* block)
 {
@@ -381,9 +441,10 @@ mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* p
 }
 
 
-static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) {
+static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool local, void* p) mi_attr_noexcept {
   mi_page_t* const page = _mi_segment_page_of(segment, p);
   mi_block_t* const block = (mi_page_has_aligned(page) ? _mi_page_ptr_unalign(segment, page, p) : (mi_block_t*)p);
+  mi_stat_free(page, block);
   _mi_free_block(page, local, block);
 }
 
@@ -392,7 +453,7 @@ static void mi_decl_noinline mi_free_generic(const mi_segment_t* segment, bool l
 // (and secure mode) if this was a valid pointer.
 static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* msg) 
 {
-  UNUSED(msg);
+  MI_UNUSED(msg);
 #if (MI_DEBUG>0)
   if (mi_unlikely(((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0)) {
     _mi_error_message(EINVAL, "%s: invalid (unaligned) pointer: %p\n", msg, p);
@@ -414,43 +475,34 @@ static inline mi_segment_t* mi_checked_ptr_segment(const void* p, const char* ms
 #endif
 #if (MI_DEBUG>0 || MI_SECURE>=4)
   if (mi_unlikely(_mi_ptr_cookie(segment) != segment->cookie)) {
-    _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", p);
+    _mi_error_message(EINVAL, "%s: pointer does not point to a valid heap space: %p\n", msg, p);
+    return NULL;
   }
 #endif
   return segment;
 }
 
-
-// Free a block
+// Free a block 
 void mi_free(void* p) mi_attr_noexcept
 {
-  const mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free");
+  mi_segment_t* const segment = mi_checked_ptr_segment(p,"mi_free");
   if (mi_unlikely(segment == NULL)) return; 
 
-  const uintptr_t tid = _mi_thread_id();
+  mi_threadid_t tid = _mi_thread_id();
   mi_page_t* const page = _mi_segment_page_of(segment, p);
-  mi_block_t* const block = (mi_block_t*)p;
-
-#if (MI_STAT>1)
-  mi_heap_t* const heap = mi_heap_get_default();
-  const size_t bsize = mi_page_usable_block_size(page);
-  mi_heap_stat_decrease(heap, malloc, bsize);
-  if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { // huge page stats are accounted for in `_mi_page_retire`
-    mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], 1);
-  }
-#endif
-
-  if (mi_likely(tid == segment->thread_id && page->flags.full_aligned == 0)) {  // the thread id matches and it is not a full page, nor has aligned blocks
+  
+  if (mi_likely(tid == mi_atomic_load_relaxed(&segment->thread_id) && page->flags.full_aligned == 0)) {  // the thread id matches and it is not a full page, nor has aligned blocks
     // local, and not full or aligned
+    mi_block_t* block = (mi_block_t*)(p);
     if (mi_unlikely(mi_check_is_double_free(page,block))) return;
     mi_check_padding(page, block);
+    mi_stat_free(page, block);
     #if (MI_DEBUG!=0)
     memset(block, MI_DEBUG_FREED, mi_page_block_size(page));
     #endif
     mi_block_set_next(page, block, page->local_free);
     page->local_free = block;
-    page->used--;
-    if (mi_unlikely(mi_page_all_free(page))) {
+    if (mi_unlikely(--page->used == 0)) {   // using this expression generates better code than: page->used--; if (mi_page_all_free(page))    
       _mi_page_retire(page);
     }
   }
@@ -484,20 +536,25 @@ bool _mi_free_delayed_block(mi_block_t* block) {
 }
 
 // Bytes available in a block
-static size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept {
-  const mi_segment_t* const segment = mi_checked_ptr_segment(p,msg);
-  if (segment==NULL) return 0;
-  const mi_page_t* const page = _mi_segment_page_of(segment, p);
-  const mi_block_t* block = (const mi_block_t*)p;
-  if (mi_unlikely(mi_page_has_aligned(page))) {
-    block = _mi_page_ptr_unalign(segment, page, p);
-    size_t size = mi_page_usable_size_of(page, block);
-    ptrdiff_t const adjust = (uint8_t*)p - (uint8_t*)block;
-    mi_assert_internal(adjust >= 0 && (size_t)adjust <= size);
-    return (size - adjust);
+mi_decl_noinline static size_t mi_page_usable_aligned_size_of(const mi_segment_t* segment, const mi_page_t* page, const void* p) mi_attr_noexcept {
+  const mi_block_t* block = _mi_page_ptr_unalign(segment, page, p);
+  const size_t size = mi_page_usable_size_of(page, block);
+  const ptrdiff_t adjust = (uint8_t*)p - (uint8_t*)block;
+  mi_assert_internal(adjust >= 0 && (size_t)adjust <= size);
+  return (size - adjust);
+}
+
+static inline size_t _mi_usable_size(const void* p, const char* msg) mi_attr_noexcept {
+  const mi_segment_t* const segment = mi_checked_ptr_segment(p, msg);
+  if (segment==NULL) return 0;  // also returns 0 if `p == NULL`
+  const mi_page_t* const page = _mi_segment_page_of(segment, p);  
+  if (mi_likely(!mi_page_has_aligned(page))) {
+    const mi_block_t* block = (const mi_block_t*)p;
+    return mi_page_usable_size_of(page, block);
   }
   else {
-    return mi_page_usable_size_of(page, block);
+    // split out to separate routine for improved code generation
+    return mi_page_usable_aligned_size_of(segment, page, p);
   }
 }
 
@@ -515,6 +572,7 @@ void* _mi_externs[] = {
   (void*)&_mi_page_malloc,
   (void*)&mi_malloc,
   (void*)&mi_malloc_small,
+  (void*)&mi_zalloc_small,
   (void*)&mi_heap_malloc,
   (void*)&mi_heap_zalloc,
   (void*)&mi_heap_malloc_small
@@ -527,19 +585,19 @@ void* _mi_externs[] = {
 // ------------------------------------------------------
 
 void mi_free_size(void* p, size_t size) mi_attr_noexcept {
-  UNUSED_RELEASE(size);
+  MI_UNUSED_RELEASE(size);
   mi_assert(p == NULL || size <= _mi_usable_size(p,"mi_free_size"));
   mi_free(p);
 }
 
 void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept {
-  UNUSED_RELEASE(alignment);
+  MI_UNUSED_RELEASE(alignment);
   mi_assert(((uintptr_t)p % alignment) == 0);
   mi_free_size(p,size);
 }
 
 void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept {
-  UNUSED_RELEASE(alignment);
+  MI_UNUSED_RELEASE(alignment);
   mi_assert(((uintptr_t)p % alignment) == 0);
   mi_free(p);
 }
@@ -565,35 +623,43 @@ mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept {
   return mi_heap_mallocn(mi_get_default_heap(),count,size);
 }
 
-// Expand in place or fail
+// Expand (or shrink) in place (or fail)
 void* mi_expand(void* p, size_t newsize) mi_attr_noexcept {
+  #if MI_PADDING
+  // we do not shrink/expand with padding enabled 
+  MI_UNUSED(p); MI_UNUSED(newsize);
+  return NULL;
+  #else
   if (p == NULL) return NULL;
-  size_t size = _mi_usable_size(p,"mi_expand");
+  const size_t size = _mi_usable_size(p,"mi_expand");
   if (newsize > size) return NULL;
   return p; // it fits
+  #endif
 }
 
-void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) {
-  if (p == NULL) return _mi_heap_malloc_zero(heap,newsize,zero);
-  size_t size = _mi_usable_size(p,"mi_realloc");
-  if (newsize <= size && newsize >= (size / 2)) {
+void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept {
+  const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL
+  if (mi_unlikely(newsize <= size && newsize >= (size / 2))) {
+    // todo: adjust potential padding to reflect the new size?
     return p;  // reallocation still fits and not more than 50% waste
   }
   void* newp = mi_heap_malloc(heap,newsize);
   if (mi_likely(newp != NULL)) {
     if (zero && newsize > size) {
       // also set last word in the previous allocation to zero to ensure any padding is zero-initialized
-      size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0);
+      const size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0);
       memset((uint8_t*)newp + start, 0, newsize - start);
     }
-    memcpy(newp, p, (newsize > size ? size : newsize));
-    mi_free(p); // only free if successful
+    if (mi_likely(p != NULL)) {
+      _mi_memcpy_aligned(newp, p, (newsize > size ? size : newsize));
+      mi_free(p); // only free the original pointer if successful
+    }
   }
   return newp;
 }
 
 void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept {
-  return _mi_heap_realloc_zero(heap, p, newsize, false);
+  return _mi_heap_realloc_zero(heap, p, newsize, false);  
 }
 
 void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept {
@@ -653,7 +719,7 @@ mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_no
   if (s == NULL) return NULL;
   size_t n = strlen(s);
   char* t = (char*)mi_heap_malloc(heap,n+1);
-  if (t != NULL) memcpy(t, s, n + 1);
+  if (t != NULL) _mi_memcpy(t, s, n + 1);
   return t;
 }
 
@@ -669,7 +735,7 @@ mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n)
   mi_assert_internal(m <= n);
   char* t = (char*)mi_heap_malloc(heap, m+1);
   if (t == NULL) return NULL;
-  memcpy(t, s, m);
+  _mi_memcpy(t, s, m);
   t[m] = 0;
   return t;
 }
@@ -704,7 +770,7 @@ mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char
 }
 #else
 #include <unistd.h>  // pathconf
-static size_t mi_path_max() {
+static size_t mi_path_max(void) {
   static size_t path_max = 0;
   if (path_max <= 0) {
     long m = pathconf("/",_PC_PATH_MAX);
@@ -748,9 +814,17 @@ but we call `exit` instead (i.e. not returning).
 #ifdef __cplusplus
 #include <new>
 static bool mi_try_new_handler(bool nothrow) {
-  std::new_handler h = std::get_new_handler();
+  #if defined(_MSC_VER) || (__cplusplus >= 201103L)
+    std::new_handler h = std::get_new_handler();
+  #else
+    std::new_handler h = std::set_new_handler();
+    std::set_new_handler(h);
+  #endif  
   if (h==NULL) {
-    if (!nothrow) throw std::bad_alloc();
+    _mi_error_message(ENOMEM, "out of memory in 'new'");      
+    if (!nothrow) {
+      throw std::bad_alloc();
+    }
     return false;
   }
   else {
@@ -759,18 +833,18 @@ static bool mi_try_new_handler(bool nothrow) {
   }
 }
 #else
-typedef void (*std_new_handler_t)();
+typedef void (*std_new_handler_t)(void);
 
 #if (defined(__GNUC__) || defined(__clang__))
-std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv() {
+std_new_handler_t __attribute((weak)) _ZSt15get_new_handlerv(void) {
   return NULL;
 }
-std_new_handler_t mi_get_new_handler() {
+static std_new_handler_t mi_get_new_handler(void) {
   return _ZSt15get_new_handlerv();
 }
 #else
 // note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`.
-std_new_handler_t mi_get_new_handler() {
+static std_new_handler_t mi_get_new_handler() {
   return NULL;
 }
 #endif
@@ -778,7 +852,10 @@ std_new_handler_t mi_get_new_handler() {
 static bool mi_try_new_handler(bool nothrow) {
   std_new_handler_t h = mi_get_new_handler();
   if (h==NULL) {
-    if (!nothrow) exit(ENOMEM);  // cannot throw in plain C, use exit as we are out of memory anyway.
+    _mi_error_message(ENOMEM, "out of memory in 'new'");       
+    if (!nothrow) {
+      abort();  // cannot throw in plain C, use abort
+    }
     return false;
   }
   else {
index bb9fc1744e0c1605f6a10205b4a425accfa90bc2..6b1e951f3421239574bb41605f0e4e64824fb5e5 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2019, Microsoft Research, Daan Leijen
+Copyright (c) 2019-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -7,51 +7,50 @@ terms of the MIT license. A copy of the license can be found in the file
 
 /* ----------------------------------------------------------------------------
 "Arenas" are fixed area's of OS memory from which we can allocate
-large blocks (>= MI_ARENA_BLOCK_SIZE, 32MiB).
+large blocks (>= MI_ARENA_MIN_BLOCK_SIZE, 4MiB).
 In contrast to the rest of mimalloc, the arenas are shared between
 threads and need to be accessed using atomic operations.
 
 Currently arenas are only used to for huge OS page (1GiB) reservations,
-otherwise it delegates to direct allocation from the OS.
+or direct OS memory reservations -- otherwise it delegates to direct allocation from the OS.
 In the future, we can expose an API to manually add more kinds of arenas
 which is sometimes needed for embedded devices or shared memory for example.
 (We can also employ this with WASI or `sbrk` systems to reserve large arenas
  on demand and be able to reuse them efficiently).
 
-The arena allocation needs to be thread safe and we use an atomic
-bitmap to allocate. The current implementation of the bitmap can
-only do this within a field (`uintptr_t`) so we can allocate at most
-blocks of 2GiB (64*32MiB) and no object can cross the boundary. This
-can lead to fragmentation but fortunately most objects will be regions
-of 256MiB in practice.
+The arena allocation needs to be thread safe and we use an atomic bitmap to allocate.
 -----------------------------------------------------------------------------*/
 #include "mimalloc.h"
 #include "mimalloc-internal.h"
 #include "mimalloc-atomic.h"
 
 #include <string.h>  // memset
+#include <errno.h> // ENOMEM
 
-#include "bitmap.inc.c"  // atomic bitmap
+#include "bitmap.h"  // atomic bitmap
 
 
 // os.c
-void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld);
+void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_stats_t* stats);
 void  _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats);
-void  _mi_os_free(void* p, size_t size, mi_stats_t* stats);
 
 void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize);
 void  _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats);
 
 bool  _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
+bool  _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
+
 
 /* -----------------------------------------------------------
   Arena allocation
 ----------------------------------------------------------- */
 
-#define MI_SEGMENT_ALIGN      MI_SEGMENT_SIZE
-#define MI_ARENA_BLOCK_SIZE   (8*MI_SEGMENT_ALIGN)     // 32MiB
-#define MI_ARENA_MAX_OBJ_SIZE (MI_BITMAP_FIELD_BITS * MI_ARENA_BLOCK_SIZE)  // 2GiB
-#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2)  // 16MiB
+
+// Block info: bit 0 contains the `in_use` bit, the upper bits the
+// size in count of arena blocks.
+typedef uintptr_t mi_block_info_t;
+#define MI_ARENA_BLOCK_SIZE   (MI_SEGMENT_SIZE)        // 8MiB  (must be at least MI_SEGMENT_ALIGN)
+#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2)  // 4MiB
 #define MI_MAX_ARENAS         (64)                     // not more than 256 (since we use 8 bits in the memid)
 
 // A memory arena descriptor
@@ -61,18 +60,18 @@ typedef struct mi_arena_s {
   size_t   field_count;                   // number of bitmap fields (where `field_count * MI_BITMAP_FIELD_BITS >= block_count`)
   int      numa_node;                     // associated NUMA node
   bool     is_zero_init;                  // is the arena zero initialized?
-  bool     is_committed;                  // is the memory committed
-  bool     is_large;                      // large OS page allocated
-  volatile _Atomic(uintptr_t) search_idx; // optimization to start the search for free blocks
+  bool     allow_decommit;                // is decommit allowed? if true, is_large should be false and blocks_committed != NULL
+  bool     is_large;                      // large- or huge OS pages (always committed)
+  _Atomic(size_t) search_idx;             // optimization to start the search for free blocks
   mi_bitmap_field_t* blocks_dirty;        // are the blocks potentially non-zero?
-  mi_bitmap_field_t* blocks_committed;    // if `!is_committed`, are the blocks committed?
-  mi_bitmap_field_t  blocks_inuse[1];       // in-place bitmap of in-use blocks (of size `field_count`)
+  mi_bitmap_field_t* blocks_committed;    // are the blocks committed? (can be NULL for memory that cannot be decommitted)
+  mi_bitmap_field_t  blocks_inuse[1];     // in-place bitmap of in-use blocks (of size `field_count`)
 } mi_arena_t;
 
 
 // The available arenas
 static mi_decl_cache_align _Atomic(mi_arena_t*) mi_arenas[MI_MAX_ARENAS];
-static mi_decl_cache_align _Atomic(uintptr_t)   mi_arena_count; // = 0
+static mi_decl_cache_align _Atomic(size_t)      mi_arena_count; // = 0
 
 
 /* -----------------------------------------------------------
@@ -104,16 +103,11 @@ static size_t mi_block_count_of_size(size_t size) {
 ----------------------------------------------------------- */
 static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx)
 {
-  const size_t fcount = arena->field_count;
-  size_t idx = mi_atomic_read(&arena->search_idx);  // start from last search
-  for (size_t visited = 0; visited < fcount; visited++, idx++) {
-    if (idx >= fcount) idx = 0;  // wrap around
-    // try to atomically claim a range of bits
-    if (mi_bitmap_try_find_claim_field(arena->blocks_inuse, idx, blocks, bitmap_idx)) {
-      mi_atomic_write(&arena->search_idx, idx);  // start search from here next time
-      return true;
-    }
-  }
+  size_t idx = 0; // mi_atomic_load_relaxed(&arena->search_idx);  // start from last search; ok to be relaxed as the exact start does not matter
+  if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx)) {
+    mi_atomic_store_relaxed(&arena->search_idx, mi_bitmap_index_field(*bitmap_idx));  // start search from found location next time around
+    return true;
+  };
   return false;
 }
 
@@ -122,25 +116,26 @@ static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t*
   Arena Allocation
 ----------------------------------------------------------- */
 
-static void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t needed_bcount,
-                                 bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+static mi_decl_noinline void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t needed_bcount,
+                                                  bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
 {
   mi_bitmap_index_t bitmap_index;
   if (!mi_arena_alloc(arena, needed_bcount, &bitmap_index)) return NULL;
 
   // claimed it! set the dirty bits (todo: no need for an atomic op here?)
-  void* p  = arena->start + (mi_bitmap_index_bit(bitmap_index)*MI_ARENA_BLOCK_SIZE);
-  *memid   = mi_arena_id_create(arena_index, bitmap_index);
-  *is_zero = mi_bitmap_claim(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL);
-  *large   = arena->is_large;
-  if (arena->is_committed) {
+  void* p    = arena->start + (mi_bitmap_index_bit(bitmap_index)*MI_ARENA_BLOCK_SIZE);
+  *memid     = mi_arena_id_create(arena_index, bitmap_index);
+  *is_zero   = _mi_bitmap_claim_across(arena->blocks_dirty, arena->field_count, needed_bcount, bitmap_index, NULL);
+  *large     = arena->is_large;
+  *is_pinned = (arena->is_large || !arena->allow_decommit);
+  if (arena->blocks_committed == NULL) {
     // always committed
     *commit = true;
   }
   else if (*commit) {
     // arena not committed as a whole, but commit requested: ensure commit now
     bool any_uncommitted;
-    mi_bitmap_claim(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted);
+    _mi_bitmap_claim_across(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index, &any_uncommitted);
     if (any_uncommitted) {
       bool commit_zero;
       _mi_os_commit(p, needed_bcount * MI_ARENA_BLOCK_SIZE, &commit_zero, tld->stats);
@@ -149,78 +144,101 @@ static void* mi_arena_alloc_from(mi_arena_t* arena, size_t arena_index, size_t n
   }
   else {
     // no need to commit, but check if already fully committed
-    *commit = mi_bitmap_is_claimed(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index);
+    *commit = _mi_bitmap_is_claimed_across(arena->blocks_committed, arena->field_count, needed_bcount, bitmap_index);
   }
   return p;
 }
 
-void* _mi_arena_alloc_aligned(size_t size, size_t alignment,
-                              bool* commit, bool* large, bool* is_zero,
+static mi_decl_noinline void* mi_arena_allocate(int numa_node, size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+{  
+  MI_UNUSED_RELEASE(alignment);
+  mi_assert_internal(alignment <= MI_SEGMENT_ALIGN);
+  const size_t max_arena = mi_atomic_load_relaxed(&mi_arena_count);  
+  const size_t bcount = mi_block_count_of_size(size);
+  if (mi_likely(max_arena == 0)) return NULL;
+  mi_assert_internal(size <= bcount*MI_ARENA_BLOCK_SIZE);
+
+  // try numa affine allocation
+  for (size_t i = 0; i < max_arena; i++) {
+    mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
+    if (arena==NULL) break; // end reached
+    if ((arena->numa_node<0 || arena->numa_node==numa_node) && // numa local?
+      (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages
+    {
+      void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_pinned, is_zero, memid, tld);
+      mi_assert_internal((uintptr_t)p % alignment == 0);
+      if (p != NULL) {
+        return p;
+      }
+    }
+  }
+
+  // try from another numa node instead..
+  for (size_t i = 0; i < max_arena; i++) {
+    mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
+    if (arena==NULL) break; // end reached
+    if ((arena->numa_node>=0 && arena->numa_node!=numa_node) && // not numa local!
+      (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages
+    {
+      void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_pinned, is_zero, memid, tld);
+      mi_assert_internal((uintptr_t)p % alignment == 0);
+      if (p != NULL) {
+        return p;
+      }
+    }
+  }
+  return NULL;
+}
+
+
+void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero,
                               size_t* memid, mi_os_tld_t* tld)
 {
-  mi_assert_internal(commit != NULL && large != NULL && is_zero != NULL && memid != NULL && tld != NULL);
+  mi_assert_internal(commit != NULL && is_pinned != NULL && is_zero != NULL && memid != NULL && tld != NULL);
   mi_assert_internal(size > 0);
   *memid   = MI_MEMID_OS;
   *is_zero = false;
+  *is_pinned = false;
 
-  // try to allocate in an arena if the alignment is small enough
-  // and the object is not too large or too small.
-  if (alignment <= MI_SEGMENT_ALIGN &&
-      size <= MI_ARENA_MAX_OBJ_SIZE &&
-      size >= MI_ARENA_MIN_OBJ_SIZE)
-  {
-    const size_t bcount = mi_block_count_of_size(size);
-    const int numa_node = _mi_os_numa_node(tld); // current numa node
-
-    mi_assert_internal(size <= bcount*MI_ARENA_BLOCK_SIZE);
-    // try numa affine allocation
-    for (size_t i = 0; i < MI_MAX_ARENAS; i++) {
-      mi_arena_t* arena = mi_atomic_read_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
-      if (arena==NULL) break; // end reached
-      if ((arena->numa_node<0 || arena->numa_node==numa_node) && // numa local?
-          (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages
-      {
-        void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld);
-        mi_assert_internal((uintptr_t)p % alignment == 0);
-        if (p != NULL) return p;
-      }
-    }
-    // try from another numa node instead..
-    for (size_t i = 0; i < MI_MAX_ARENAS; i++) {
-      mi_arena_t* arena = mi_atomic_read_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
-      if (arena==NULL) break; // end reached
-      if ((arena->numa_node>=0 && arena->numa_node!=numa_node) && // not numa local!
-          (*large || !arena->is_large)) // large OS pages allowed, or arena is not large OS pages
-      {
-        void* p = mi_arena_alloc_from(arena, i, bcount, commit, large, is_zero, memid, tld);
-        mi_assert_internal((uintptr_t)p % alignment == 0);
-        if (p != NULL) return p;
-      }
-    }
+  bool default_large = false;
+  if (large==NULL) large = &default_large;     // ensure `large != NULL`
+  const int numa_node = _mi_os_numa_node(tld); // current numa node
+
+  // try to allocate in an arena if the alignment is small enough and the object is not too small (as for heap meta data)
+  if (size >= MI_ARENA_MIN_OBJ_SIZE && alignment <= MI_SEGMENT_ALIGN) {
+    void* p = mi_arena_allocate(numa_node, size, alignment, commit, large, is_pinned, is_zero, memid, tld);
+    if (p != NULL) return p;
   }
 
   // finally, fall back to the OS
+  if (mi_option_is_enabled(mi_option_limit_os_alloc)) {
+    errno = ENOMEM;
+    return NULL;
+  }
   *is_zero = true;
-  *memid   = MI_MEMID_OS;
-  return _mi_os_alloc_aligned(size, alignment, *commit, large, tld);
+  *memid   = MI_MEMID_OS;  
+  void* p = _mi_os_alloc_aligned(size, alignment, *commit, large, tld->stats);
+  if (p != NULL) *is_pinned = *large;
+  return p;
 }
 
-void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
 {
-  return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, commit, large, is_zero, memid, tld);
+  return _mi_arena_alloc_aligned(size, MI_ARENA_BLOCK_SIZE, commit, large, is_pinned, is_zero, memid, tld);
 }
 
 /* -----------------------------------------------------------
   Arena free
 ----------------------------------------------------------- */
 
-void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats) {
-  mi_assert_internal(size > 0 && stats != NULL);
+void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_os_tld_t* tld) {
+  mi_assert_internal(size > 0 && tld->stats != NULL);
   if (p==NULL) return;
   if (size==0) return;
+
   if (memid == MI_MEMID_OS) {
     // was a direct OS allocation, pass through
-    _mi_os_free_ex(p, size, all_committed, stats);
+    _mi_os_free_ex(p, size, all_committed, tld->stats);
   }
   else {
     // allocated in an arena
@@ -228,8 +246,10 @@ void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_s
     size_t bitmap_idx;
     mi_arena_id_indices(memid, &arena_idx, &bitmap_idx);
     mi_assert_internal(arena_idx < MI_MAX_ARENAS);
-    mi_arena_t* arena = mi_atomic_read_ptr_relaxed(mi_arena_t,&mi_arenas[arena_idx]);
+    mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t,&mi_arenas[arena_idx]);
     mi_assert_internal(arena != NULL);
+    const size_t blocks = mi_block_count_of_size(size);
+    // checks
     if (arena == NULL) {
       _mi_error_message(EINVAL, "trying to free from non-existent arena: %p, size %zu, memid: 0x%zx\n", p, size, memid);
       return;
@@ -239,9 +259,18 @@ void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_s
       _mi_error_message(EINVAL, "trying to free from non-existent arena block: %p, size %zu, memid: 0x%zx\n", p, size, memid);
       return;
     }
-    const size_t blocks = mi_block_count_of_size(size);
-    bool ones = mi_bitmap_unclaim(arena->blocks_inuse, arena->field_count, blocks, bitmap_idx);
-    if (!ones) {
+    // potentially decommit
+    if (!arena->allow_decommit || arena->blocks_committed == NULL) {
+      mi_assert_internal(all_committed); // note: may be not true as we may "pretend" to be not committed (in segment.c)
+    }
+    else {
+      mi_assert_internal(arena->blocks_committed != NULL);
+      _mi_os_decommit(p, blocks * MI_ARENA_BLOCK_SIZE, tld->stats); // ok if this fails
+      _mi_bitmap_unclaim_across(arena->blocks_committed, arena->field_count, blocks, bitmap_idx);
+    }
+    // and make it available to others again 
+    bool all_inuse = _mi_bitmap_unclaim_across(arena->blocks_inuse, arena->field_count, blocks, bitmap_idx);
+    if (!all_inuse) {
       _mi_error_message(EAGAIN, "trying to free an already freed block: %p, size %zu\n", p, size);
       return;
     };
@@ -254,24 +283,109 @@ void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_s
 
 static bool mi_arena_add(mi_arena_t* arena) {
   mi_assert_internal(arena != NULL);
-  mi_assert_internal((uintptr_t)mi_atomic_read_ptr_relaxed(uint8_t,&arena->start) % MI_SEGMENT_ALIGN == 0);
+  mi_assert_internal((uintptr_t)mi_atomic_load_ptr_relaxed(uint8_t,&arena->start) % MI_SEGMENT_ALIGN == 0);
   mi_assert_internal(arena->block_count > 0);
 
-  uintptr_t i = mi_atomic_increment(&mi_arena_count);
+  size_t i = mi_atomic_increment_acq_rel(&mi_arena_count);
   if (i >= MI_MAX_ARENAS) {
-    mi_atomic_decrement(&mi_arena_count);
+    mi_atomic_decrement_acq_rel(&mi_arena_count);
     return false;
   }
-  mi_atomic_write_ptr(mi_arena_t,&mi_arenas[i], arena);
+  mi_atomic_store_ptr_release(mi_arena_t,&mi_arenas[i], arena);
   return true;
 }
 
+bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept
+{
+  if (size < MI_ARENA_BLOCK_SIZE) return false;
+
+  if (is_large) {
+    mi_assert_internal(is_committed);
+    is_committed = true;
+  }
+  
+  const size_t bcount = size / MI_ARENA_BLOCK_SIZE; 
+  const size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS);
+  const size_t bitmaps = (is_committed ? 2 : 3);
+  const size_t asize  = sizeof(mi_arena_t) + (bitmaps*fields*sizeof(mi_bitmap_field_t));
+  mi_arena_t* arena   = (mi_arena_t*)_mi_os_alloc(asize, &_mi_stats_main); // TODO: can we avoid allocating from the OS?
+  if (arena == NULL) return false;
+
+  arena->block_count = bcount;
+  arena->field_count = fields;
+  arena->start = (uint8_t*)start;
+  arena->numa_node    = numa_node; // TODO: or get the current numa node if -1? (now it allows anyone to allocate on -1)
+  arena->is_large     = is_large;
+  arena->is_zero_init = is_zero;
+  arena->allow_decommit = !is_large && !is_committed; // only allow decommit for initially uncommitted memory
+  arena->search_idx   = 0;
+  arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap
+  arena->blocks_committed = (!arena->allow_decommit ? NULL : &arena->blocks_inuse[2*fields]); // just after dirty bitmap
+  // the bitmaps are already zero initialized due to os_alloc
+  // initialize committed bitmap?
+  if (arena->blocks_committed != NULL && is_committed) {
+    memset((void*)arena->blocks_committed, 0xFF, fields*sizeof(mi_bitmap_field_t)); // cast to void* to avoid atomic warning
+  }
+  // and claim leftover blocks if needed (so we never allocate there)
+  ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount;
+  mi_assert_internal(post >= 0);
+  if (post > 0) {
+    // don't use leftover bits at the end
+    mi_bitmap_index_t postidx = mi_bitmap_index_create(fields - 1, MI_BITMAP_FIELD_BITS - post);
+    _mi_bitmap_claim(arena->blocks_inuse, fields, post, postidx, NULL);
+  }
+
+  mi_arena_add(arena);
+  return true;
+}
+
+// Reserve a range of regular OS memory
+int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept 
+{
+  size = _mi_align_up(size, MI_ARENA_BLOCK_SIZE); // at least one block
+  bool large = allow_large;
+  void* start = _mi_os_alloc_aligned(size, MI_SEGMENT_ALIGN, commit, &large, &_mi_stats_main);
+  if (start==NULL) return ENOMEM;
+  if (!mi_manage_os_memory(start, size, (large || commit), large, true, -1)) {
+    _mi_os_free_ex(start, size, commit, &_mi_stats_main);
+    _mi_verbose_message("failed to reserve %zu k memory\n", _mi_divide_up(size,1024));
+    return ENOMEM;
+  }
+  _mi_verbose_message("reserved %zu KiB memory%s\n", _mi_divide_up(size,1024), large ? " (in large os pages)" : "");
+  return 0;
+}
+
+static size_t mi_debug_show_bitmap(const char* prefix, mi_bitmap_field_t* fields, size_t field_count ) {
+  size_t inuse_count = 0;
+  for (size_t i = 0; i < field_count; i++) {
+    char buf[MI_BITMAP_FIELD_BITS + 1];
+    uintptr_t field = mi_atomic_load_relaxed(&fields[i]);
+    for (size_t bit = 0; bit < MI_BITMAP_FIELD_BITS; bit++) {
+      bool inuse = ((((uintptr_t)1 << bit) & field) != 0);
+      if (inuse) inuse_count++;
+      buf[MI_BITMAP_FIELD_BITS - 1 - bit] = (inuse ? 'x' : '.');
+    }
+    buf[MI_BITMAP_FIELD_BITS] = 0;
+    _mi_verbose_message("%s%s\n", prefix, buf);
+  }
+  return inuse_count;
+}
+
+void mi_debug_show_arenas(void) mi_attr_noexcept {
+  size_t max_arenas = mi_atomic_load_relaxed(&mi_arena_count);
+  for (size_t i = 0; i < max_arenas; i++) {
+    mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
+    if (arena == NULL) break;
+    size_t inuse_count = 0;
+    _mi_verbose_message("arena %zu: %zu blocks with %zu fields\n", i, arena->block_count, arena->field_count);
+    inuse_count += mi_debug_show_bitmap("  ", arena->blocks_inuse, arena->field_count);
+    _mi_verbose_message("  blocks in use ('x'): %zu\n", inuse_count);
+  }
+}
 
 /* -----------------------------------------------------------
   Reserve a huge page arena.
 ----------------------------------------------------------- */
-#include <errno.h> // ENOMEM
-
 // reserve at a specific numa node
 int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept {
   if (pages==0) return 0;
@@ -281,40 +395,15 @@ int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msec
   size_t pages_reserved = 0;
   void* p = _mi_os_alloc_huge_os_pages(pages, numa_node, timeout_msecs, &pages_reserved, &hsize);
   if (p==NULL || pages_reserved==0) {
-    _mi_warning_message("failed to reserve %zu gb huge pages\n", pages);
+    _mi_warning_message("failed to reserve %zu GiB huge pages\n", pages);
     return ENOMEM;
   }
-  _mi_verbose_message("numa node %i: reserved %zu gb huge pages (of the %zu gb requested)\n", numa_node, pages_reserved, pages);
+  _mi_verbose_message("numa node %i: reserved %zu GiB huge pages (of the %zu GiB requested)\n", numa_node, pages_reserved, pages);
 
-  size_t bcount = mi_block_count_of_size(hsize);
-  size_t fields = _mi_divide_up(bcount, MI_BITMAP_FIELD_BITS);
-  size_t asize = sizeof(mi_arena_t) + (2*fields*sizeof(mi_bitmap_field_t));
-  mi_arena_t* arena = (mi_arena_t*)_mi_os_alloc(asize, &_mi_stats_main); // TODO: can we avoid allocating from the OS?
-  if (arena == NULL) {
+  if (!mi_manage_os_memory(p, hsize, true, true, true, numa_node)) {
     _mi_os_free_huge_pages(p, hsize, &_mi_stats_main);
     return ENOMEM;
   }
-  arena->block_count = bcount;
-  arena->field_count = fields;
-  arena->start = (uint8_t*)p;
-  arena->numa_node = numa_node; // TODO: or get the current numa node if -1? (now it allows anyone to allocate on -1)
-  arena->is_large = true;
-  arena->is_zero_init = true;
-  arena->is_committed = true;
-  arena->search_idx = 0;
-  arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap
-  arena->blocks_committed = NULL;
-  // the bitmaps are already zero initialized due to os_alloc
-  // just claim leftover blocks if needed
-  ptrdiff_t post = (fields * MI_BITMAP_FIELD_BITS) - bcount;
-  mi_assert_internal(post >= 0);
-  if (post > 0) {
-    // don't use leftover bits at the end
-    mi_bitmap_index_t postidx = mi_bitmap_index_create(fields - 1, MI_BITMAP_FIELD_BITS - post);
-    mi_bitmap_claim(arena->blocks_inuse, fields, post, postidx, NULL);
-  }
-
-  mi_arena_add(arena);
   return 0;
 }
 
@@ -348,7 +437,7 @@ int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t
 }
 
 int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept {
-  UNUSED(max_secs);
+  MI_UNUSED(max_secs);
   _mi_warning_message("mi_reserve_huge_os_pages is deprecated: use mi_reserve_huge_os_pages_interleave/at instead\n");
   if (pages_reserved != NULL) *pages_reserved = 0;
   int err = mi_reserve_huge_os_pages_interleave(pages, 0, (size_t)(max_secs * 1000.0));
diff --git a/extlib/mimalloc/src/bitmap.c b/extlib/mimalloc/src/bitmap.c
new file mode 100644 (file)
index 0000000..af6de0a
--- /dev/null
@@ -0,0 +1,395 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2019-2021 Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+
+/* ----------------------------------------------------------------------------
+Concurrent bitmap that can set/reset sequences of bits atomically,
+represeted as an array of fields where each field is a machine word (`size_t`)
+
+There are two api's; the standard one cannot have sequences that cross
+between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
+(this is used in region allocation)
+
+The `_across` postfixed functions do allow sequences that can cross over
+between the fields. (This is used in arena allocation)
+---------------------------------------------------------------------------- */
+
+#include "mimalloc.h"
+#include "mimalloc-internal.h"
+#include "bitmap.h"
+
+/* -----------------------------------------------------------
+  Bitmap definition
+----------------------------------------------------------- */
+
+// The bit mask for a given number of blocks at a specified bit index.
+static inline size_t mi_bitmap_mask_(size_t count, size_t bitidx) {
+  mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS);
+  mi_assert_internal(count > 0);
+  if (count >= MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL;
+  if (count == 0) return 0;
+  return ((((size_t)1 << count) - 1) << bitidx);
+}
+
+
+/* -----------------------------------------------------------
+  Claim a bit sequence atomically
+----------------------------------------------------------- */
+
+// Try to atomically claim a sequence of `count` bits in a single
+// field at `idx` in `bitmap`. Returns `true` on success.
+inline bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx)
+{
+  mi_assert_internal(bitmap_idx != NULL);
+  mi_assert_internal(count <= MI_BITMAP_FIELD_BITS);
+  mi_assert_internal(count > 0);
+  mi_bitmap_field_t* field = &bitmap[idx];
+  size_t map  = mi_atomic_load_relaxed(field);
+  if (map==MI_BITMAP_FIELD_FULL) return false; // short cut
+
+  // search for 0-bit sequence of length count
+  const size_t mask = mi_bitmap_mask_(count, 0);
+  const size_t bitidx_max = MI_BITMAP_FIELD_BITS - count;
+
+#ifdef MI_HAVE_FAST_BITSCAN
+  size_t bitidx = mi_ctz(~map);    // quickly find the first zero bit if possible
+#else
+  size_t bitidx = 0;               // otherwise start at 0
+#endif
+  size_t m = (mask << bitidx);     // invariant: m == mask shifted by bitidx
+
+  // scan linearly for a free range of zero bits
+  while (bitidx <= bitidx_max) {
+    const size_t mapm = map & m;
+    if (mapm == 0) {  // are the mask bits free at bitidx?
+      mi_assert_internal((m >> bitidx) == mask); // no overflow?
+      const size_t newmap = map | m;
+      mi_assert_internal((newmap^map) >> bitidx == mask);
+      if (!mi_atomic_cas_weak_acq_rel(field, &map, newmap)) {  // TODO: use strong cas here?
+        // no success, another thread claimed concurrently.. keep going (with updated `map`)
+        continue;
+      }
+      else {
+        // success, we claimed the bits!
+        *bitmap_idx = mi_bitmap_index_create(idx, bitidx);
+        return true;
+      }
+    }
+    else {
+      // on to the next bit range
+#ifdef MI_HAVE_FAST_BITSCAN
+      const size_t shift = (count == 1 ? 1 : mi_bsr(mapm) - bitidx + 1);
+      mi_assert_internal(shift > 0 && shift <= count);
+#else
+      const size_t shift = 1;
+#endif
+      bitidx += shift;
+      m <<= shift;
+    }
+  }
+  // no bits found
+  return false;
+}
+
+// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success.
+// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
+// `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields.
+bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
+  size_t idx = start_field_idx;
+  for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
+    if (idx >= bitmap_fields) idx = 0; // wrap
+    if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/*
+// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success.
+// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never span fields.
+bool _mi_bitmap_try_find_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t count, mi_bitmap_index_t* bitmap_idx) {
+  return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, 0, count, bitmap_idx);
+}
+*/
+
+// Set `count` bits at `bitmap_idx` to 0 atomically
+// Returns `true` if all `count` bits were 1 previously.
+bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  const size_t idx = mi_bitmap_index_field(bitmap_idx);
+  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
+  const size_t mask = mi_bitmap_mask_(count, bitidx);
+  mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
+  // mi_assert_internal((bitmap[idx] & mask) == mask);
+  size_t prev = mi_atomic_and_acq_rel(&bitmap[idx], ~mask);
+  return ((prev & mask) == mask);
+}
+
+
+// Set `count` bits at `bitmap_idx` to 1 atomically
+// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
+bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) {
+  const size_t idx = mi_bitmap_index_field(bitmap_idx);
+  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
+  const size_t mask = mi_bitmap_mask_(count, bitidx);
+  mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
+  //mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
+  size_t prev = mi_atomic_or_acq_rel(&bitmap[idx], mask);
+  if (any_zero != NULL) *any_zero = ((prev & mask) != mask);
+  return ((prev & mask) == 0);
+}
+
+// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one.
+static bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) {
+  const size_t idx = mi_bitmap_index_field(bitmap_idx);
+  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
+  const size_t mask = mi_bitmap_mask_(count, bitidx);
+  mi_assert_internal(bitmap_fields > idx); MI_UNUSED(bitmap_fields);
+  size_t field = mi_atomic_load_relaxed(&bitmap[idx]);
+  if (any_ones != NULL) *any_ones = ((field & mask) != 0);
+  return ((field & mask) == mask);
+}
+
+bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL);
+}
+
+bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  bool any_ones;
+  mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones);
+  return any_ones;
+}
+
+
+//--------------------------------------------------------------------------
+// the `_across` functions work on bitmaps where sequences can cross over
+// between the fields. This is used in arena allocation
+//--------------------------------------------------------------------------
+
+// Try to atomically claim a sequence of `count` bits starting from the field 
+// at `idx` in `bitmap` and crossing into subsequent fields. Returns `true` on success.
+static bool mi_bitmap_try_find_claim_field_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t idx, const size_t count, const size_t retries, mi_bitmap_index_t* bitmap_idx)
+{
+  mi_assert_internal(bitmap_idx != NULL);
+  
+  // check initial trailing zeros
+  mi_bitmap_field_t* field = &bitmap[idx];
+  size_t map = mi_atomic_load_relaxed(field);  
+  const size_t initial = mi_clz(map);  // count of initial zeros starting at idx
+  mi_assert_internal(initial <= MI_BITMAP_FIELD_BITS);
+  if (initial == 0)     return false;
+  if (initial >= count) return _mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx);     // no need to cross fields
+  if (_mi_divide_up(count - initial, MI_BITMAP_FIELD_BITS) >= (bitmap_fields - idx)) return false; // not enough entries
+
+  // scan ahead
+  size_t found = initial;
+  size_t mask = 0;     // mask bits for the final field
+  while(found < count) {
+    field++;
+    map = mi_atomic_load_relaxed(field);
+    const size_t mask_bits = (found + MI_BITMAP_FIELD_BITS <= count ? MI_BITMAP_FIELD_BITS : (count - found));
+    mask = mi_bitmap_mask_(mask_bits, 0);
+    if ((map & mask) != 0) return false;
+    found += mask_bits;
+  }
+  mi_assert_internal(field < &bitmap[bitmap_fields]);
+
+  // found range of zeros up to the final field; mask contains mask in the final field
+  // now claim it atomically
+  mi_bitmap_field_t* const final_field = field;
+  const size_t final_mask = mask;
+  mi_bitmap_field_t* const initial_field = &bitmap[idx];
+  const size_t initial_mask = mi_bitmap_mask_(initial, MI_BITMAP_FIELD_BITS - initial);
+
+  // initial field
+  size_t newmap;
+  field = initial_field;
+  map = mi_atomic_load_relaxed(field);
+  do {
+    newmap = map | initial_mask;
+    if ((map & initial_mask) != 0) { goto rollback; };
+  } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
+  
+  // intermediate fields
+  while (++field < final_field) {
+    newmap = MI_BITMAP_FIELD_FULL;
+    map = 0;
+    if (!mi_atomic_cas_strong_acq_rel(field, &map, newmap)) { goto rollback; }
+  }
+  
+  // final field
+  mi_assert_internal(field == final_field);
+  map = mi_atomic_load_relaxed(field);
+  do {
+    newmap = map | final_mask;
+    if ((map & final_mask) != 0) { goto rollback; }
+  } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
+
+  // claimed!
+  *bitmap_idx = mi_bitmap_index_create(idx, MI_BITMAP_FIELD_BITS - initial);
+  return true;
+
+rollback: 
+  // roll back intermediate fields
+  while (--field > initial_field) {
+    newmap = 0;
+    map = MI_BITMAP_FIELD_FULL;
+    mi_assert_internal(mi_atomic_load_relaxed(field) == map);
+    mi_atomic_store_release(field, newmap);
+  }
+  if (field == initial_field) {
+    map = mi_atomic_load_relaxed(field);
+    do {
+      mi_assert_internal((map & initial_mask) == initial_mask);
+      newmap = map & ~initial_mask;
+    } while (!mi_atomic_cas_strong_acq_rel(field, &map, newmap));
+  }  
+  // retry? (we make a recursive call instead of goto to be able to use const declarations)
+  if (retries < 4) {
+    return mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, retries+1, bitmap_idx);
+  }
+  else {
+    return false;
+  }
+}
+
+
+// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success.
+// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
+bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx) {
+  mi_assert_internal(count > 0);
+  if (count==1) return _mi_bitmap_try_find_from_claim(bitmap, bitmap_fields, start_field_idx, count, bitmap_idx);
+  size_t idx = start_field_idx;
+  for (size_t visited = 0; visited < bitmap_fields; visited++, idx++) {
+    if (idx >= bitmap_fields) idx = 0; // wrap
+    // try to claim inside the field
+    if (count <= MI_BITMAP_FIELD_BITS) {
+      if (_mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
+        return true;
+      }
+    }
+    // try to claim across fields
+    if (mi_bitmap_try_find_claim_field_across(bitmap, bitmap_fields, idx, count, 0, bitmap_idx)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Helper for masks across fields; returns the mid count, post_mask may be 0
+static size_t mi_bitmap_mask_across(mi_bitmap_index_t bitmap_idx, size_t bitmap_fields, size_t count, size_t* pre_mask, size_t* mid_mask, size_t* post_mask) {
+  MI_UNUSED_RELEASE(bitmap_fields);
+  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
+  if (mi_likely(bitidx + count <= MI_BITMAP_FIELD_BITS)) {
+    *pre_mask = mi_bitmap_mask_(count, bitidx);
+    *mid_mask = 0;
+    *post_mask = 0;
+    mi_assert_internal(mi_bitmap_index_field(bitmap_idx) < bitmap_fields);
+    return 0;
+  }
+  else {
+    const size_t pre_bits = MI_BITMAP_FIELD_BITS - bitidx;
+    mi_assert_internal(pre_bits < count);
+    *pre_mask = mi_bitmap_mask_(pre_bits, bitidx);
+    count -= pre_bits;
+    const size_t mid_count = (count / MI_BITMAP_FIELD_BITS);
+    *mid_mask = MI_BITMAP_FIELD_FULL;
+    count %= MI_BITMAP_FIELD_BITS;
+    *post_mask = (count==0 ? 0 : mi_bitmap_mask_(count, 0));
+    mi_assert_internal(mi_bitmap_index_field(bitmap_idx) + mid_count + (count==0 ? 0 : 1) < bitmap_fields);
+    return mid_count;
+  }
+}
+
+// Set `count` bits at `bitmap_idx` to 0 atomically
+// Returns `true` if all `count` bits were 1 previously.
+bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  size_t idx = mi_bitmap_index_field(bitmap_idx);
+  size_t pre_mask;
+  size_t mid_mask;
+  size_t post_mask;
+  size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);  
+  bool all_one = true;
+  mi_bitmap_field_t* field = &bitmap[idx];
+  size_t prev = mi_atomic_and_acq_rel(field++, ~pre_mask);
+  if ((prev & pre_mask) != pre_mask) all_one = false;
+  while(mid_count-- > 0) {
+    prev = mi_atomic_and_acq_rel(field++, ~mid_mask);
+    if ((prev & mid_mask) != mid_mask) all_one = false;
+  }
+  if (post_mask!=0) {
+    prev = mi_atomic_and_acq_rel(field, ~post_mask);
+    if ((prev & post_mask) != post_mask) all_one = false;
+  }
+  return all_one;  
+}
+
+// Set `count` bits at `bitmap_idx` to 1 atomically
+// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
+bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero) {
+  size_t idx = mi_bitmap_index_field(bitmap_idx);
+  size_t pre_mask;
+  size_t mid_mask;
+  size_t post_mask;
+  size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
+  bool all_zero = true;
+  bool any_zero = false;
+  _Atomic(size_t)*field = &bitmap[idx];
+  size_t prev = mi_atomic_or_acq_rel(field++, pre_mask);
+  if ((prev & pre_mask) != 0) all_zero = false;
+  if ((prev & pre_mask) != pre_mask) any_zero = true;
+  while (mid_count-- > 0) {
+    prev = mi_atomic_or_acq_rel(field++, mid_mask);
+    if ((prev & mid_mask) != 0) all_zero = false;
+    if ((prev & mid_mask) != mid_mask) any_zero = true;
+  }
+  if (post_mask!=0) {
+    prev = mi_atomic_or_acq_rel(field, post_mask);
+    if ((prev & post_mask) != 0) all_zero = false;
+    if ((prev & post_mask) != post_mask) any_zero = true;
+  }
+  if (pany_zero != NULL) *pany_zero = any_zero;
+  return all_zero;
+}
+
+
+// Returns `true` if all `count` bits were 1. 
+// `any_ones` is `true` if there was at least one bit set to one.
+static bool mi_bitmap_is_claimedx_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_ones) {
+  size_t idx = mi_bitmap_index_field(bitmap_idx);
+  size_t pre_mask;
+  size_t mid_mask;
+  size_t post_mask;
+  size_t mid_count = mi_bitmap_mask_across(bitmap_idx, bitmap_fields, count, &pre_mask, &mid_mask, &post_mask);
+  bool all_ones = true;
+  bool any_ones = false;
+  mi_bitmap_field_t* field = &bitmap[idx];
+  size_t prev = mi_atomic_load_relaxed(field++);
+  if ((prev & pre_mask) != pre_mask) all_ones = false;
+  if ((prev & pre_mask) != 0) any_ones = true;
+  while (mid_count-- > 0) {
+    prev = mi_atomic_load_relaxed(field++);
+    if ((prev & mid_mask) != mid_mask) all_ones = false;
+    if ((prev & mid_mask) != 0) any_ones = true;
+  }
+  if (post_mask!=0) {
+    prev = mi_atomic_load_relaxed(field);
+    if ((prev & post_mask) != post_mask) all_ones = false;
+    if ((prev & post_mask) != 0) any_ones = true;
+  }  
+  if (pany_ones != NULL) *pany_ones = any_ones;
+  return all_ones;
+}
+
+bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  return mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, NULL);
+}
+
+bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
+  bool any_ones;
+  mi_bitmap_is_claimedx_across(bitmap, bitmap_fields, count, bitmap_idx, &any_ones);
+  return any_ones;
+}
diff --git a/extlib/mimalloc/src/bitmap.h b/extlib/mimalloc/src/bitmap.h
new file mode 100644 (file)
index 0000000..7bd3106
--- /dev/null
@@ -0,0 +1,107 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2019-2020 Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+
+/* ----------------------------------------------------------------------------
+Concurrent bitmap that can set/reset sequences of bits atomically,
+represeted as an array of fields where each field is a machine word (`size_t`)
+
+There are two api's; the standard one cannot have sequences that cross
+between the bitmap fields (and a sequence must be <= MI_BITMAP_FIELD_BITS).
+(this is used in region allocation)
+
+The `_across` postfixed functions do allow sequences that can cross over
+between the fields. (This is used in arena allocation)
+---------------------------------------------------------------------------- */
+#pragma once
+#ifndef MI_BITMAP_H
+#define MI_BITMAP_H
+
+/* -----------------------------------------------------------
+  Bitmap definition
+----------------------------------------------------------- */
+
+#define MI_BITMAP_FIELD_BITS   (8*MI_SIZE_SIZE)
+#define MI_BITMAP_FIELD_FULL   (~((size_t)0))   // all bits set
+
+// An atomic bitmap of `size_t` fields
+typedef _Atomic(size_t)  mi_bitmap_field_t;
+typedef mi_bitmap_field_t*  mi_bitmap_t;
+
+// A bitmap index is the index of the bit in a bitmap.
+typedef size_t mi_bitmap_index_t;
+
+// Create a bit index.
+static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) {
+  mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS);
+  return (idx*MI_BITMAP_FIELD_BITS) + bitidx;
+}
+
+// Create a bit index.
+static inline mi_bitmap_index_t mi_bitmap_index_create_from_bit(size_t full_bitidx) {  
+  return mi_bitmap_index_create(full_bitidx / MI_BITMAP_FIELD_BITS, full_bitidx % MI_BITMAP_FIELD_BITS);
+}
+
+// Get the field index from a bit index.
+static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) {
+  return (bitmap_idx / MI_BITMAP_FIELD_BITS);
+}
+
+// Get the bit index in a bitmap field
+static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) {
+  return (bitmap_idx % MI_BITMAP_FIELD_BITS);
+}
+
+// Get the full bit index
+static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) {
+  return bitmap_idx;
+}
+
+/* -----------------------------------------------------------
+  Claim a bit sequence atomically
+----------------------------------------------------------- */
+
+// Try to atomically claim a sequence of `count` bits in a single
+// field at `idx` in `bitmap`. Returns `true` on success.
+bool _mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
+
+// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
+// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never cross fields.
+bool _mi_bitmap_try_find_from_claim(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
+
+// Set `count` bits at `bitmap_idx` to 0 atomically
+// Returns `true` if all `count` bits were 1 previously.
+bool _mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+
+// Set `count` bits at `bitmap_idx` to 1 atomically
+// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
+bool _mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero);
+
+bool _mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+bool _mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+
+
+//--------------------------------------------------------------------------
+// the `_across` functions work on bitmaps where sequences can cross over
+// between the fields. This is used in arena allocation
+//--------------------------------------------------------------------------
+
+// Find `count` bits of zeros and set them to 1 atomically; returns `true` on success.
+// Starts at idx, and wraps around to search in all `bitmap_fields` fields.
+bool _mi_bitmap_try_find_from_claim_across(mi_bitmap_t bitmap, const size_t bitmap_fields, const size_t start_field_idx, const size_t count, mi_bitmap_index_t* bitmap_idx);
+
+// Set `count` bits at `bitmap_idx` to 0 atomically
+// Returns `true` if all `count` bits were 1 previously.
+bool _mi_bitmap_unclaim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+
+// Set `count` bits at `bitmap_idx` to 1 atomically
+// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
+bool _mi_bitmap_claim_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* pany_zero);
+
+bool _mi_bitmap_is_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+bool _mi_bitmap_is_any_claimed_across(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx);
+
+#endif
diff --git a/extlib/mimalloc/src/bitmap.inc.c b/extlib/mimalloc/src/bitmap.inc.c
deleted file mode 100644 (file)
index c3813a4..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/* ----------------------------------------------------------------------------
-Copyright (c) 2019, Microsoft Research, Daan Leijen
-This is free software; you can redistribute it and/or modify it under the
-terms of the MIT license. A copy of the license can be found in the file
-"LICENSE" at the root of this distribution.
------------------------------------------------------------------------------*/
-
-/* ----------------------------------------------------------------------------
-This file is meant to be included in other files for efficiency.
-It implements a bitmap that can set/reset sequences of bits atomically
-and is used to concurrently claim memory ranges.
-
-A bitmap is an array of fields where each field is a machine word (`uintptr_t`)
-
-A current limitation is that the bit sequences cannot cross fields
-and that the sequence must be smaller or equal to the bits in a field.
----------------------------------------------------------------------------- */
-#pragma once
-#ifndef MI_BITMAP_C
-#define MI_BITMAP_C
-
-#include "mimalloc.h"
-#include "mimalloc-internal.h"
-
-/* -----------------------------------------------------------
-  Bitmap definition
------------------------------------------------------------ */
-
-#define MI_BITMAP_FIELD_BITS   (8*MI_INTPTR_SIZE)
-#define MI_BITMAP_FIELD_FULL   (~((uintptr_t)0))   // all bits set
-
-// An atomic bitmap of `uintptr_t` fields
-typedef volatile _Atomic(uintptr_t)  mi_bitmap_field_t;
-typedef mi_bitmap_field_t*           mi_bitmap_t;
-
-// A bitmap index is the index of the bit in a bitmap.
-typedef size_t mi_bitmap_index_t;
-
-// Create a bit index.
-static inline mi_bitmap_index_t mi_bitmap_index_create(size_t idx, size_t bitidx) {
-  mi_assert_internal(bitidx < MI_BITMAP_FIELD_BITS);
-  return (idx*MI_BITMAP_FIELD_BITS) + bitidx;
-}
-
-// Get the field index from a bit index.
-static inline size_t mi_bitmap_index_field(mi_bitmap_index_t bitmap_idx) {
-  return (bitmap_idx / MI_BITMAP_FIELD_BITS);
-}
-
-// Get the bit index in a bitmap field
-static inline size_t mi_bitmap_index_bit_in_field(mi_bitmap_index_t bitmap_idx) {
-  return (bitmap_idx % MI_BITMAP_FIELD_BITS);
-}
-
-// Get the full bit index
-static inline size_t mi_bitmap_index_bit(mi_bitmap_index_t bitmap_idx) {
-  return bitmap_idx;
-}
-
-
-// The bit mask for a given number of blocks at a specified bit index.
-static inline uintptr_t mi_bitmap_mask_(size_t count, size_t bitidx) {
-  mi_assert_internal(count + bitidx <= MI_BITMAP_FIELD_BITS);
-  if (count == MI_BITMAP_FIELD_BITS) return MI_BITMAP_FIELD_FULL;
-  return ((((uintptr_t)1 << count) - 1) << bitidx);
-}
-
-
-/* -----------------------------------------------------------
-  Use bit scan forward/reverse to quickly find the first zero bit if it is available
------------------------------------------------------------ */
-#if defined(_MSC_VER)
-#define MI_HAVE_BITSCAN
-#include <intrin.h>
-static inline size_t mi_bsf(uintptr_t x) {
-  if (x==0) return 8*MI_INTPTR_SIZE;
-  DWORD idx;
-  MI_64(_BitScanForward)(&idx, x);
-  return idx;
-}
-static inline size_t mi_bsr(uintptr_t x) {
-  if (x==0) return 8*MI_INTPTR_SIZE;
-  DWORD idx;
-  MI_64(_BitScanReverse)(&idx, x);
-  return idx;
-}
-#elif defined(__GNUC__) || defined(__clang__)
-#include <limits.h> // LONG_MAX
-#define MI_HAVE_BITSCAN
-#if (INTPTR_MAX == LONG_MAX)
-# define MI_L(x)  x##l
-#else
-# define MI_L(x)  x##ll
-#endif
-static inline size_t mi_bsf(uintptr_t x) {
-  return (x==0 ? 8*MI_INTPTR_SIZE : MI_L(__builtin_ctz)(x));
-}
-static inline size_t mi_bsr(uintptr_t x) {
-  return (x==0 ? 8*MI_INTPTR_SIZE : (8*MI_INTPTR_SIZE - 1) - MI_L(__builtin_clz)(x));
-}
-#endif
-
-/* -----------------------------------------------------------
-  Claim a bit sequence atomically
------------------------------------------------------------ */
-
-// Try to atomically claim a sequence of `count` bits at in `idx`
-// in the bitmap field. Returns `true` on success.
-static inline bool mi_bitmap_try_claim_field(mi_bitmap_t bitmap, size_t bitmap_fields, const size_t count, mi_bitmap_index_t bitmap_idx) {
-  const size_t idx = mi_bitmap_index_field(bitmap_idx);
-  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
-  const uintptr_t mask = mi_bitmap_mask_(count, bitidx);
-  mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields);
-  mi_assert_internal(bitidx + count <= MI_BITMAP_FIELD_BITS);
-
-  uintptr_t field = mi_atomic_read_relaxed(&bitmap[idx]);
-  if ((field & mask) == 0) { // free?
-    if (mi_atomic_cas_strong(&bitmap[idx], (field|mask), field)) {
-      // claimed!
-      return true;
-    }
-  }
-  return false;
-}
-
-
-// Try to atomically claim a sequence of `count` bits in a single
-// field at `idx` in `bitmap`. Returns `true` on success.
-static inline bool mi_bitmap_try_find_claim_field(mi_bitmap_t bitmap, size_t idx, const size_t count, mi_bitmap_index_t* bitmap_idx)
-{
-  mi_assert_internal(bitmap_idx != NULL);
-  volatile _Atomic(uintptr_t)* field = &bitmap[idx];
-  uintptr_t map  = mi_atomic_read(field);
-  if (map==MI_BITMAP_FIELD_FULL) return false; // short cut
-
-  // search for 0-bit sequence of length count
-  const uintptr_t mask = mi_bitmap_mask_(count, 0);
-  const size_t    bitidx_max = MI_BITMAP_FIELD_BITS - count;
-
-#ifdef MI_HAVE_BITSCAN
-  size_t bitidx = mi_bsf(~map);    // quickly find the first zero bit if possible
-#else
-  size_t bitidx = 0;               // otherwise start at 0
-#endif
-  uintptr_t m = (mask << bitidx);     // invariant: m == mask shifted by bitidx
-
-  // scan linearly for a free range of zero bits
-  while (bitidx <= bitidx_max) {
-    if ((map & m) == 0) {  // are the mask bits free at bitidx?
-      mi_assert_internal((m >> bitidx) == mask); // no overflow?
-      const uintptr_t newmap = map | m;
-      mi_assert_internal((newmap^map) >> bitidx == mask);
-      if (!mi_atomic_cas_weak(field, newmap, map)) {  // TODO: use strong cas here?
-        // no success, another thread claimed concurrently.. keep going
-        map = mi_atomic_read(field);
-        continue;
-      }
-      else {
-        // success, we claimed the bits!
-        *bitmap_idx = mi_bitmap_index_create(idx, bitidx);
-        return true;
-      }
-    }
-    else {
-      // on to the next bit range
-#ifdef MI_HAVE_BITSCAN
-      const size_t shift = (count == 1 ? 1 : mi_bsr(map & m) - bitidx + 1);
-      mi_assert_internal(shift > 0 && shift <= count);
-#else
-      const size_t shift = 1;
-#endif
-      bitidx += shift;
-      m <<= shift;
-    }
-  }
-  // no bits found
-  return false;
-}
-
-
-// Find `count` bits of 0 and set them to 1 atomically; returns `true` on success.
-// For now, `count` can be at most MI_BITMAP_FIELD_BITS and will never span fields.
-static inline bool mi_bitmap_try_find_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t* bitmap_idx) {
-  for (size_t idx = 0; idx < bitmap_fields; idx++) {
-    if (mi_bitmap_try_find_claim_field(bitmap, idx, count, bitmap_idx)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Set `count` bits at `bitmap_idx` to 0 atomically
-// Returns `true` if all `count` bits were 1 previously.
-static inline bool mi_bitmap_unclaim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
-  const size_t idx = mi_bitmap_index_field(bitmap_idx);
-  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
-  const uintptr_t mask = mi_bitmap_mask_(count, bitidx);
-  mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields);
-  // mi_assert_internal((bitmap[idx] & mask) == mask);
-  uintptr_t prev = mi_atomic_and(&bitmap[idx], ~mask);
-  return ((prev & mask) == mask);
-}
-
-
-// Set `count` bits at `bitmap_idx` to 1 atomically
-// Returns `true` if all `count` bits were 0 previously. `any_zero` is `true` if there was at least one zero bit.
-static inline bool mi_bitmap_claim(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_zero) {
-  const size_t idx = mi_bitmap_index_field(bitmap_idx);
-  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
-  const uintptr_t mask = mi_bitmap_mask_(count, bitidx);
-  mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields);
-  //mi_assert_internal(any_zero != NULL || (bitmap[idx] & mask) == 0);
-  uintptr_t prev = mi_atomic_or(&bitmap[idx], mask);
-  if (any_zero != NULL) *any_zero = ((prev & mask) != mask);
-  return ((prev & mask) == 0);
-}
-
-// Returns `true` if all `count` bits were 1. `any_ones` is `true` if there was at least one bit set to one.
-static inline bool mi_bitmap_is_claimedx(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx, bool* any_ones) {
-  const size_t idx = mi_bitmap_index_field(bitmap_idx);
-  const size_t bitidx = mi_bitmap_index_bit_in_field(bitmap_idx);
-  const uintptr_t mask = mi_bitmap_mask_(count, bitidx);
-  mi_assert_internal(bitmap_fields > idx); UNUSED(bitmap_fields);
-  uintptr_t field = mi_atomic_read_relaxed(&bitmap[idx]);
-  if (any_ones != NULL) *any_ones = ((field & mask) != 0);
-  return ((field & mask) == mask);
-}
-
-static inline bool mi_bitmap_is_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
-  return mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, NULL);
-}
-
-static inline bool mi_bitmap_is_any_claimed(mi_bitmap_t bitmap, size_t bitmap_fields, size_t count, mi_bitmap_index_t bitmap_idx) {
-  bool any_ones;
-  mi_bitmap_is_claimedx(bitmap, bitmap_fields, count, bitmap_idx, &any_ones);
-  return any_ones;
-}
-
-
-#endif
index aab7e126e12648aec255f12e96ccf10c10c4041a..816d961ae9fe4e67cc7cb31730ae829d307bf6e1 100644 (file)
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -11,6 +11,9 @@ terms of the MIT license. A copy of the license can be found in the file
 
 #include <string.h>  // memset, memcpy
 
+#if defined(_MSC_VER) && (_MSC_VER < 1920)
+#pragma warning(disable:4204)  // non-constant aggregate initializer
+#endif
 
 /* -----------------------------------------------------------
   Helpers
@@ -47,9 +50,9 @@ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void
 
 #if MI_DEBUG>=2
 static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
-  UNUSED(arg1);
-  UNUSED(arg2);
-  UNUSED(pq);
+  MI_UNUSED(arg1);
+  MI_UNUSED(arg2);
+  MI_UNUSED(pq);
   mi_assert_internal(mi_page_heap(page) == heap);
   mi_segment_t* segment = _mi_page_segment(page);
   mi_assert_internal(segment->thread_id == heap->thread_id);
@@ -83,8 +86,8 @@ typedef enum mi_collect_e {
 
 
 static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg_collect, void* arg2 ) {
-  UNUSED(arg2);
-  UNUSED(heap);
+  MI_UNUSED(arg2);
+  MI_UNUSED(heap);
   mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL));
   mi_collect_t collect = *((mi_collect_t*)arg_collect);
   _mi_page_free_collect(page, collect >= MI_FORCE);
@@ -101,28 +104,31 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t
 }
 
 static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
-  UNUSED(arg1);
-  UNUSED(arg2);
-  UNUSED(heap);
-  UNUSED(pq);
+  MI_UNUSED(arg1);
+  MI_UNUSED(arg2);
+  MI_UNUSED(heap);
+  MI_UNUSED(pq);
   _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
   return true; // don't break
 }
 
 static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
 {
-  if (!mi_heap_is_initialized(heap)) return;
-  _mi_deferred_free(heap, collect >= MI_FORCE);
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return;
+
+  const bool force = collect >= MI_FORCE;  
+  _mi_deferred_free(heap, force);
 
   // note: never reclaim on collect but leave it to threads that need storage to reclaim 
-  if (
-  #ifdef NDEBUG
+  const bool force_main = 
+    #ifdef NDEBUG
       collect == MI_FORCE
-  #else
+    #else
       collect >= MI_FORCE
-  #endif
-    && _mi_is_main_thread() && mi_heap_is_backing(heap) && !heap->no_reclaim)
-  {
+    #endif
+      && _mi_is_main_thread() && mi_heap_is_backing(heap) && !heap->no_reclaim;
+
+  if (force_main) {
     // the main thread is abandoned (end-of-program), try to reclaim all abandoned segments.
     // if all memory is freed by now, all segments should be freed.
     _mi_abandoned_reclaim_all(heap, &heap->tld->segments);
@@ -138,20 +144,28 @@ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
   _mi_heap_delayed_free(heap);
 
   // collect retired pages
-  _mi_heap_collect_retired(heap, collect >= MI_FORCE);
+  _mi_heap_collect_retired(heap, force);
 
   // collect all pages owned by this thread
   mi_heap_visit_pages(heap, &mi_heap_page_collect, &collect, NULL);
-  mi_assert_internal( collect != MI_ABANDON || mi_atomic_read_ptr(mi_block_t,&heap->thread_delayed_free) == NULL );
+  mi_assert_internal( collect != MI_ABANDON || mi_atomic_load_ptr_acquire(mi_block_t,&heap->thread_delayed_free) == NULL );
+
+  // collect abandoned segments (in particular, decommit expired parts of segments in the abandoned segment list)
+  // note: forced decommit can be quite expensive if many threads are created/destroyed so we do not force on abandonment
+  _mi_abandoned_collect(heap, collect == MI_FORCE /* force? */, &heap->tld->segments);
 
-  // collect segment caches
-  if (collect >= MI_FORCE) {
+  // collect segment local caches
+  if (force) {
     _mi_segment_thread_collect(&heap->tld->segments);
   }
 
+  // decommit in global segment caches
+  // note: forced decommit can be quite expensive if many threads are created/destroyed so we do not force on abandonment
+  _mi_segment_cache_collect( collect == MI_FORCE, &heap->tld->os);  
+
   // collect regions on program-exit (or shared library unload)
-  if (collect >= MI_FORCE && _mi_is_main_thread() && mi_heap_is_backing(heap)) {
-    _mi_mem_collect(&heap->tld->os);
+  if (force && _mi_is_main_thread() && mi_heap_is_backing(heap)) {
+    //_mi_mem_collect(&heap->tld->os);
   }
 }
 
@@ -190,7 +204,7 @@ mi_heap_t* mi_heap_new(void) {
   mi_heap_t* bheap = mi_heap_get_backing();
   mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t);  // todo: OS allocate in secure mode?
   if (heap==NULL) return NULL;
-  memcpy(heap, &_mi_heap_empty, sizeof(mi_heap_t));
+  _mi_memcpy_aligned(heap, &_mi_heap_empty, sizeof(mi_heap_t));
   heap->tld = bheap->tld;
   heap->thread_id = _mi_thread_id();
   _mi_random_split(&bheap->random, &heap->random);
@@ -210,13 +224,14 @@ uintptr_t _mi_heap_random_next(mi_heap_t* heap) {
 
 // zero out the page queues
 static void mi_heap_reset_pages(mi_heap_t* heap) {
+  mi_assert_internal(heap != NULL);
   mi_assert_internal(mi_heap_is_initialized(heap));
   // TODO: copy full empty heap instead?
   memset(&heap->pages_free_direct, 0, sizeof(heap->pages_free_direct));
 #ifdef MI_MEDIUM_DIRECT
   memset(&heap->pages_free_medium, 0, sizeof(heap->pages_free_medium));
 #endif
-  memcpy(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages));
+  _mi_memcpy_aligned(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages));
   heap->thread_delayed_free = NULL;
   heap->page_count = 0;
 }
@@ -225,6 +240,7 @@ static void mi_heap_reset_pages(mi_heap_t* heap) {
 static void mi_heap_free(mi_heap_t* heap) {
   mi_assert(heap != NULL);
   mi_assert_internal(mi_heap_is_initialized(heap));
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return;
   if (mi_heap_is_backing(heap)) return; // dont free the backing heap
 
   // reset default
@@ -257,29 +273,32 @@ static void mi_heap_free(mi_heap_t* heap) {
 ----------------------------------------------------------- */
 
 static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
-  UNUSED(arg1);
-  UNUSED(arg2);
-  UNUSED(heap);
-  UNUSED(pq);
+  MI_UNUSED(arg1);
+  MI_UNUSED(arg2);
+  MI_UNUSED(heap);
+  MI_UNUSED(pq);
 
   // ensure no more thread_delayed_free will be added
   _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
 
   // stats
   const size_t bsize = mi_page_block_size(page);
-  if (bsize > MI_LARGE_OBJ_SIZE_MAX) {
-    if (bsize > MI_HUGE_OBJ_SIZE_MAX) {
-      _mi_stat_decrease(&heap->tld->stats.giant, bsize);
+  if (bsize > MI_MEDIUM_OBJ_SIZE_MAX) {
+    if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
+      mi_heap_stat_decrease(heap, large, bsize);
     }
     else {
-      _mi_stat_decrease(&heap->tld->stats.huge, bsize);
+      mi_heap_stat_decrease(heap, huge, bsize);
     }
   }
-#if (MI_STAT>1)
+#if (MI_STAT)
   _mi_page_free_collect(page, false);  // update used count
   const size_t inuse = page->used;
   if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
-    mi_heap_stat_decrease(heap, normal[_mi_bin(bsize)], inuse);
+    mi_heap_stat_decrease(heap, normal, bsize * inuse);
+#if (MI_STAT>1)
+    mi_heap_stat_decrease(heap, normal_bins[_mi_bin(bsize)], inuse);
+#endif
   }
   mi_heap_stat_decrease(heap, malloc, bsize * inuse);  // todo: off for aligned blocks...
 #endif
@@ -307,7 +326,7 @@ void mi_heap_destroy(mi_heap_t* heap) {
   mi_assert(mi_heap_is_initialized(heap));
   mi_assert(heap->no_reclaim);
   mi_assert_expensive(mi_heap_is_valid(heap));
-  if (!mi_heap_is_initialized(heap)) return;
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return;
   if (!heap->no_reclaim) {
     // don't free in case it may contain reclaimed pages
     mi_heap_delete(heap);
@@ -325,7 +344,7 @@ void mi_heap_destroy(mi_heap_t* heap) {
   Safe Heap delete
 ----------------------------------------------------------- */
 
-// Tranfer the pages from one heap to the other
+// Transfer the pages from one heap to the other
 static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) {
   mi_assert_internal(heap!=NULL);
   if (from==NULL || from->page_count == 0) return;
@@ -351,7 +370,9 @@ static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) {
   // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a 
   // the regular `_mi_free_delayed_block` which is safe.
   _mi_heap_delayed_free(from);  
-  mi_assert_internal(from->thread_delayed_free == NULL);
+  #if !defined(_MSC_VER) || (_MSC_VER > 1900) // somehow the following line gives an error in VS2015, issue #353
+  mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_block_t,&from->thread_delayed_free) == NULL);
+  #endif
 
   // and reset the `from` heap
   mi_heap_reset_pages(from);  
@@ -363,7 +384,7 @@ void mi_heap_delete(mi_heap_t* heap)
   mi_assert(heap != NULL);
   mi_assert(mi_heap_is_initialized(heap));
   mi_assert_expensive(mi_heap_is_valid(heap));
-  if (!mi_heap_is_initialized(heap)) return;
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return;
 
   if (!mi_heap_is_backing(heap)) {
     // tranfer still used pages to the backing heap
@@ -378,8 +399,9 @@ void mi_heap_delete(mi_heap_t* heap)
 }
 
 mi_heap_t* mi_heap_set_default(mi_heap_t* heap) {
+  mi_assert(heap != NULL);
   mi_assert(mi_heap_is_initialized(heap));
-  if (!mi_heap_is_initialized(heap)) return NULL;
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return NULL;
   mi_assert_expensive(mi_heap_is_valid(heap));
   mi_heap_t* old = mi_get_default_heap();
   _mi_heap_set_default_direct(heap);
@@ -405,14 +427,14 @@ static mi_heap_t* mi_heap_of_block(const void* p) {
 
 bool mi_heap_contains_block(mi_heap_t* heap, const void* p) {
   mi_assert(heap != NULL);
-  if (!mi_heap_is_initialized(heap)) return false;
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return false;
   return (heap == mi_heap_of_block(p));
 }
 
 
 static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* p, void* vfound) {
-  UNUSED(heap);
-  UNUSED(pq);
+  MI_UNUSED(heap);
+  MI_UNUSED(pq);
   bool* found = (bool*)vfound;
   mi_segment_t* segment = _mi_page_segment(page);
   void* start = _mi_page_start(segment, page, NULL);
@@ -423,7 +445,7 @@ static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_pa
 
 bool mi_heap_check_owned(mi_heap_t* heap, const void* p) {
   mi_assert(heap != NULL);
-  if (!mi_heap_is_initialized(heap)) return false;
+  if (heap==NULL || !mi_heap_is_initialized(heap)) return false;
   if (((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) return false;  // only aligned pointers
   bool found = false;
   mi_heap_visit_pages(heap, &mi_heap_page_check_owned, (void*)p, &found);
@@ -459,13 +481,14 @@ static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_v
   if (page->used == 0) return true;
 
   const size_t bsize = mi_page_block_size(page);
+  const size_t ubsize = mi_page_usable_block_size(page); // without padding
   size_t   psize;
   uint8_t* pstart = _mi_page_start(_mi_page_segment(page), page, &psize);
 
   if (page->capacity == 1) {
     // optimize page with one block
     mi_assert_internal(page->used == 1 && page->free == NULL);
-    return visitor(mi_page_heap(page), area, pstart, bsize, arg);
+    return visitor(mi_page_heap(page), area, pstart, ubsize, arg);
   }
 
   // create a bitmap of free blocks.
@@ -499,7 +522,7 @@ static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_v
     else if ((m & ((uintptr_t)1 << bit)) == 0) {
       used_count++;
       uint8_t* block = pstart + (i * bsize);
-      if (!visitor(mi_page_heap(page), area, block, bsize, arg)) return false;
+      if (!visitor(mi_page_heap(page), area, block, ubsize, arg)) return false;
     }
   }
   mi_assert_internal(page->used == used_count);
@@ -510,17 +533,19 @@ typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_
 
 
 static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* vfun, void* arg) {
-  UNUSED(heap);
-  UNUSED(pq);
+  MI_UNUSED(heap);
+  MI_UNUSED(pq);
   mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun;
   mi_heap_area_ex_t xarea;
   const size_t bsize = mi_page_block_size(page);
+  const size_t ubsize = mi_page_usable_block_size(page);
   xarea.page = page;
   xarea.area.reserved = page->reserved * bsize;
   xarea.area.committed = page->capacity * bsize;
   xarea.area.blocks = _mi_page_start(_mi_page_segment(page), page, NULL);
-  xarea.area.used = page->used;
-  xarea.area.block_size = bsize;
+  xarea.area.used = page->used * bsize;
+  xarea.area.block_size = ubsize;
+  xarea.area.full_block_size = bsize;
   return fun(heap, &xarea, arg);
 }
 
index 1724bd21c19d4f5df28602e39c583ab39ac5144c..19124afef9da4c4fcd3cf0f58fa3b192dff28c30 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -25,9 +25,12 @@ const mi_page_t _mi_page_empty = {
   0,       // used
   0,       // xblock_size
   NULL,    // local_free
-  ATOMIC_VAR_INIT(0), // xthread_free
-  ATOMIC_VAR_INIT(0), // xheap
+  MI_ATOMIC_VAR_INIT(0), // xthread_free
+  MI_ATOMIC_VAR_INIT(0), // xheap
   NULL, NULL
+  #if MI_INTPTR_SIZE==8
+  , { 0 }  // padding
+  #endif
 };
 
 #define MI_PAGE_EMPTY() ((mi_page_t*)&_mi_page_empty)
@@ -54,8 +57,8 @@ const mi_page_t _mi_page_empty = {
     QNULL( 10240), QNULL( 12288), QNULL( 14336), QNULL( 16384), QNULL( 20480), QNULL( 24576), QNULL( 28672), QNULL( 32768), /* 56 */ \
     QNULL( 40960), QNULL( 49152), QNULL( 57344), QNULL( 65536), QNULL( 81920), QNULL( 98304), QNULL(114688), QNULL(131072), /* 64 */ \
     QNULL(163840), QNULL(196608), QNULL(229376), QNULL(262144), QNULL(327680), QNULL(393216), QNULL(458752), QNULL(524288), /* 72 */ \
-    QNULL(MI_LARGE_OBJ_WSIZE_MAX + 1  /* 655360, Huge queue */), \
-    QNULL(MI_LARGE_OBJ_WSIZE_MAX + 2) /* Full queue */ }
+    QNULL(MI_MEDIUM_OBJ_WSIZE_MAX + 1  /* 655360, Huge queue */), \
+    QNULL(MI_MEDIUM_OBJ_WSIZE_MAX + 2) /* Full queue */ }
 
 #define MI_STAT_COUNT_NULL()  {0,0,0,0}
 
@@ -73,11 +76,23 @@ const mi_page_t _mi_page_empty = {
   MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
   MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
   MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
-  MI_STAT_COUNT_NULL(), \
-  { 0, 0 }, { 0, 0 }, { 0, 0 },  \
+  MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \
+  { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },     \
   { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \
   MI_STAT_COUNT_END_NULL()
 
+
+// Empty slice span queues for every bin
+#define SQNULL(sz)  { NULL, NULL, sz }
+#define MI_SEGMENT_SPAN_QUEUES_EMPTY \
+  { SQNULL(1), \
+    SQNULL(     1), SQNULL(     2), SQNULL(     3), SQNULL(     4), SQNULL(     5), SQNULL(     6), SQNULL(     7), SQNULL(    10), /*  8 */ \
+    SQNULL(    12), SQNULL(    14), SQNULL(    16), SQNULL(    20), SQNULL(    24), SQNULL(    28), SQNULL(    32), SQNULL(    40), /* 16 */ \
+    SQNULL(    48), SQNULL(    56), SQNULL(    64), SQNULL(    80), SQNULL(    96), SQNULL(   112), SQNULL(   128), SQNULL(   160), /* 24 */ \
+    SQNULL(   192), SQNULL(   224), SQNULL(   256), SQNULL(   320), SQNULL(   384), SQNULL(   448), SQNULL(   512), SQNULL(   640), /* 32 */ \
+    SQNULL(   768), SQNULL(   896), SQNULL(  1024) /* 35 */ }
+
+
 // --------------------------------------------------------
 // Statically allocate an empty heap as the initial
 // thread local value for the default heap,
@@ -87,11 +102,11 @@ const mi_page_t _mi_page_empty = {
 // may lead to allocation itself on some platforms)
 // --------------------------------------------------------
 
-const mi_heap_t _mi_heap_empty = {
+mi_decl_cache_align const mi_heap_t _mi_heap_empty = {
   NULL,
   MI_SMALL_PAGES_EMPTY,
   MI_PAGE_QUEUES_EMPTY,
-  ATOMIC_VAR_INIT(NULL),
+  MI_ATOMIC_VAR_INIT(NULL),
   0,                // tid
   0,                // cookie
   { 0, 0 },         // keys
@@ -102,6 +117,18 @@ const mi_heap_t _mi_heap_empty = {
   false
 };
 
+#define tld_empty_stats  ((mi_stats_t*)((uint8_t*)&tld_empty + offsetof(mi_tld_t,stats)))
+#define tld_empty_os     ((mi_os_tld_t*)((uint8_t*)&tld_empty + offsetof(mi_tld_t,os)))
+
+mi_decl_cache_align static const mi_tld_t tld_empty = {
+  0,
+  false,
+  NULL, NULL,
+  { MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, tld_empty_stats, tld_empty_os }, // segments
+  { 0, tld_empty_stats }, // os
+  { MI_STATS_NULL }       // stats
+};
+
 // the thread-local default heap for allocation
 mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty;
 
@@ -109,11 +136,8 @@ extern mi_heap_t _mi_heap_main;
 
 static mi_tld_t tld_main = {
   0, false,
-  &_mi_heap_main, &_mi_heap_main,
-  { { NULL, NULL }, {NULL ,NULL}, {NULL ,NULL, 0},
-    0, 0, 0, 0, 0, 0, NULL,
-    &tld_main.stats, &tld_main.os
-  }, // segments
+  &_mi_heap_main, & _mi_heap_main,
+  { MI_SEGMENT_SPAN_QUEUES_EMPTY, 0, 0, 0, 0, &tld_main.stats, &tld_main.os }, // segments
   { 0, &tld_main.stats },  // os
   { MI_STATS_NULL }       // stats
 };
@@ -122,7 +146,7 @@ mi_heap_t _mi_heap_main = {
   &tld_main,
   MI_SMALL_PAGES_EMPTY,
   MI_PAGE_QUEUES_EMPTY,
-  ATOMIC_VAR_INIT(NULL),
+  MI_ATOMIC_VAR_INIT(NULL),
   0,                // thread id
   0,                // initial cookie
   { 0, 0 },         // the key of the main heap can be fixed (unlike page keys that need to be secure!)
@@ -141,7 +165,7 @@ mi_stats_t _mi_stats_main = { MI_STATS_NULL };
 static void mi_heap_main_init(void) {
   if (_mi_heap_main.cookie == 0) {
     _mi_heap_main.thread_id = _mi_thread_id();
-    _mi_heap_main.cookie = _os_random_weak((uintptr_t)&mi_heap_main_init);
+    _mi_heap_main.cookie = _mi_os_random_weak((uintptr_t)&mi_heap_main_init);
     _mi_random_init(&_mi_heap_main.random);
     _mi_heap_main.keys[0] = _mi_heap_random_next(&_mi_heap_main);
     _mi_heap_main.keys[1] = _mi_heap_random_next(&_mi_heap_main);
@@ -164,6 +188,68 @@ typedef struct mi_thread_data_s {
   mi_tld_t   tld;
 } mi_thread_data_t;
 
+
+// Thread meta-data is allocated directly from the OS. For
+// some programs that do not use thread pools and allocate and
+// destroy many OS threads, this may causes too much overhead 
+// per thread so we maintain a small cache of recently freed metadata.
+
+#define TD_CACHE_SIZE (8)
+static _Atomic(mi_thread_data_t*) td_cache[TD_CACHE_SIZE];
+
+static mi_thread_data_t* mi_thread_data_alloc(void) {
+  // try to find thread metadata in the cache
+  mi_thread_data_t* td;
+  for (int i = 0; i < TD_CACHE_SIZE; i++) {
+    td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]);
+    if (td != NULL) {
+      td = mi_atomic_exchange_ptr_acq_rel(mi_thread_data_t, &td_cache[i], NULL); 
+      if (td != NULL) {
+        return td;
+      }
+    }
+  }
+  // if that fails, allocate directly from the OS
+  td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main);
+  if (td == NULL) {
+    // if this fails, try once more. (issue #257)
+    td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main);
+    if (td == NULL) {
+      // really out of memory
+      _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t));
+    }
+  }
+  return td;
+}
+
+static void mi_thread_data_free( mi_thread_data_t* tdfree ) {
+  // try to add the thread metadata to the cache
+  for (int i = 0; i < TD_CACHE_SIZE; i++) {
+    mi_thread_data_t* td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]);
+    if (td == NULL) {
+      mi_thread_data_t* expected = NULL;
+      if (mi_atomic_cas_ptr_weak_acq_rel(mi_thread_data_t, &td_cache[i], &expected, tdfree)) {
+        return;
+      }
+    }
+  }
+  // if that fails, just free it directly
+  _mi_os_free(tdfree, sizeof(mi_thread_data_t), &_mi_stats_main);
+}
+
+static void mi_thread_data_collect(void) {
+  // free all thread metadata from the cache
+  for (int i = 0; i < TD_CACHE_SIZE; i++) {
+    mi_thread_data_t* td = mi_atomic_load_ptr_relaxed(mi_thread_data_t, &td_cache[i]);
+    if (td != NULL) {
+      td = mi_atomic_exchange_ptr_acq_rel(mi_thread_data_t, &td_cache[i], NULL);
+      if (td != NULL) {
+        _mi_os_free( td, sizeof(mi_thread_data_t), &_mi_stats_main );
+      }
+    }
+  }
+}
+
 // Initialize the thread local default heap, called from `mi_thread_init`
 static bool _mi_heap_init(void) {
   if (mi_heap_is_initialized(mi_get_default_heap())) return true;
@@ -176,20 +262,14 @@ static bool _mi_heap_init(void) {
   }
   else {
     // use `_mi_os_alloc` to allocate directly from the OS
-    mi_thread_data_t* td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main); // Todo: more efficient allocation?
-    if (td == NULL) {
-      // if this fails, try once more. (issue #257)
-      td = (mi_thread_data_t*)_mi_os_alloc(sizeof(mi_thread_data_t), &_mi_stats_main);
-      if (td == NULL) {
-        // really out of memory
-        _mi_error_message(ENOMEM, "unable to allocate thread local heap metadata (%zu bytes)\n", sizeof(mi_thread_data_t));
-        return false;
-      }
-    }
+    mi_thread_data_t* td = mi_thread_data_alloc();
+    if (td == NULL) return false;
+
     // OS allocated so already zero initialized
     mi_tld_t*  tld = &td->tld;
     mi_heap_t* heap = &td->heap;
-    memcpy(heap, &_mi_heap_empty, sizeof(*heap));
+    _mi_memcpy_aligned(tld, &tld_empty, sizeof(*tld));
+    _mi_memcpy_aligned(heap, &_mi_heap_empty, sizeof(*heap));
     heap->thread_id = _mi_thread_id();
     _mi_random_init(&heap->random);
     heap->cookie  = _mi_heap_random_next(heap) | 1;
@@ -201,7 +281,7 @@ static bool _mi_heap_init(void) {
     tld->segments.stats = &tld->stats;
     tld->segments.os = &tld->os;
     tld->os.stats = &tld->stats;
-    _mi_heap_set_default_direct(heap);
+    _mi_heap_set_default_direct(heap);    
   }
   return false;
 }
@@ -235,23 +315,26 @@ static bool _mi_heap_done(mi_heap_t* heap) {
     _mi_heap_collect_abandon(heap);
   }
   
-
   // merge stats
-  _mi_stats_done(&heap->tld->stats);
+  _mi_stats_done(&heap->tld->stats);  
 
   // free if not the main thread
   if (heap != &_mi_heap_main) {
-    mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id());
-    _mi_os_free(heap, sizeof(mi_thread_data_t), &_mi_stats_main);
+    // the following assertion does not always hold for huge segments as those are always treated
+    // as abondened: one may allocate it in one thread, but deallocate in another in which case
+    // the count can be too large or negative. todo: perhaps not count huge segments? see issue #363
+    // mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id());
+    mi_thread_data_free((mi_thread_data_t*)heap);
   }
-#if 0  
-  // never free the main thread even in debug mode; if a dll is linked statically with mimalloc,
-  // there may still be delete/free calls after the mi_fls_done is called. Issue #207
   else {
+    mi_thread_data_collect(); // free cached thread metadata  
+    #if 0  
+    // never free the main thread even in debug mode; if a dll is linked statically with mimalloc,
+    // there may still be delete/free calls after the mi_fls_done is called. Issue #207
     _mi_heap_destroy_pages(heap);
     mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main);
+    #endif
   }
-#endif
   return false;
 }
 
@@ -275,12 +358,6 @@ static bool _mi_heap_done(mi_heap_t* heap) {
 
 static void _mi_thread_done(mi_heap_t* default_heap);
 
-#ifdef __wasi__
-// no pthreads in the WebAssembly Standard Interface
-#elif !defined(_WIN32)
-#define MI_USE_PTHREADS
-#endif
-
 #if defined(_WIN32) && defined(MI_SHARED_LIB)
   // nothing to do as it is done in DllMain
 #elif defined(_WIN32) && !defined(MI_SHARED_LIB)
@@ -300,7 +377,6 @@ static void _mi_thread_done(mi_heap_t* default_heap);
 #elif defined(MI_USE_PTHREADS)
   // use pthread local storage keys to detect thread ending
   // (and used with MI_TLS_PTHREADS for the default heap)
-  #include <pthread.h>
   pthread_key_t _mi_heap_default_key = (pthread_key_t)(-1);
   static void mi_pthread_done(void* value) {
     if (value!=NULL) _mi_thread_done((mi_heap_t*)value);
@@ -332,23 +408,25 @@ bool _mi_is_main_thread(void) {
   return (_mi_heap_main.thread_id==0 || _mi_heap_main.thread_id == _mi_thread_id());
 }
 
+static _Atomic(size_t) thread_count = MI_ATOMIC_VAR_INIT(1);
+
+size_t  _mi_current_thread_count(void) {
+  return mi_atomic_load_relaxed(&thread_count);
+}
+
 // This is called from the `mi_malloc_generic`
 void mi_thread_init(void) mi_attr_noexcept
 {
   // ensure our process has started already
   mi_process_init();
-
+  
   // initialize the thread local default heap
   // (this will call `_mi_heap_set_default_direct` and thus set the
   //  fiber/pthread key to a non-zero value, ensuring `_mi_thread_done` is called)
   if (_mi_heap_init()) return;  // returns true if already initialized
 
-  // don't further initialize for the main thread
-  if (_mi_is_main_thread()) return;
-
-  mi_heap_t* const heap = mi_get_default_heap();
-  if (mi_heap_is_initialized(heap)) { _mi_stat_increase(&heap->tld->stats.threads, 1); }
-
+  _mi_stat_increase(&_mi_stats_main.threads, 1);
+  mi_atomic_increment_relaxed(&thread_count);
   //_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
 }
 
@@ -357,14 +435,12 @@ void mi_thread_done(void) mi_attr_noexcept {
 }
 
 static void _mi_thread_done(mi_heap_t* heap) {
+  mi_atomic_decrement_relaxed(&thread_count);
+  _mi_stat_decrease(&_mi_stats_main.threads, 1);
+
   // check thread-id as on Windows shutdown with FLS the main (exit) thread may call this on thread-local heaps...
   if (heap->thread_id != _mi_thread_id()) return;
-
-  // stats
-  if (!_mi_is_main_thread() && mi_heap_is_initialized(heap))  {
-    _mi_stat_decrease(&heap->tld->stats.threads, 1);
-  }
-
+  
   // abandon the thread local heap
   if (_mi_heap_done(heap)) return;  // returns true if already ran
 }
@@ -405,11 +481,11 @@ static bool os_preloading = true;    // true until this module is initialized
 static bool mi_redirected = false;   // true if malloc redirects to mi_malloc
 
 // Returns true if this module has not been initialized; Don't use C runtime routines until it returns false.
-bool _mi_preloading() {
+bool _mi_preloading(void) {
   return os_preloading;
 }
 
-bool mi_is_redirected() mi_attr_noexcept {
+mi_decl_nodiscard bool mi_is_redirected(void) mi_attr_noexcept {
   return mi_redirected;
 }
 
@@ -431,7 +507,7 @@ mi_decl_export void _mi_redirect_entry(DWORD reason) {
   }
 }
 __declspec(dllimport) bool mi_allocator_init(const char** message);
-__declspec(dllimport) void mi_allocator_done();
+__declspec(dllimport) void mi_allocator_done(void);
 #ifdef __cplusplus
 }
 #endif
@@ -440,7 +516,7 @@ static bool mi_allocator_init(const char** message) {
   if (message != NULL) *message = NULL;
   return true;
 }
-static void mi_allocator_done() {
+static void mi_allocator_done(void) {
   // nothing to do
 }
 #endif
@@ -450,10 +526,12 @@ static void mi_process_load(void) {
   mi_heap_main_init();
   #if defined(MI_TLS_RECURSE_GUARD)
   volatile mi_heap_t* dummy = _mi_heap_default; // access TLS to allocate it before setting tls_initialized to true;
-  UNUSED(dummy);
+  MI_UNUSED(dummy);
   #endif
   os_preloading = false;
-  atexit(&mi_process_done);
+  #if !(defined(_WIN32) && defined(MI_SHARED_LIB))  // use Dll process detach (see below) instead of atexit (issue #521)
+  atexit(&mi_process_done);  
+  #endif
   _mi_options_init();
   mi_process_init();
   //mi_stats_reset();-
@@ -467,14 +545,32 @@ static void mi_process_load(void) {
   }
 }
 
+#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))
+#include <intrin.h>
+mi_decl_cache_align bool _mi_cpu_has_fsrm = false;
+
+static void mi_detect_cpu_features(void) {
+  // FSRM for fast rep movsb support (AMD Zen3+ (~2020) or Intel Ice Lake+ (~2017))
+  int32_t cpu_info[4];
+  __cpuid(cpu_info, 7);
+  _mi_cpu_has_fsrm = ((cpu_info[3] & (1 << 4)) != 0); // bit 4 of EDX : see <https ://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features>
+}
+#else
+static void mi_detect_cpu_features(void) {
+  // nothing
+}
+#endif
+
 // Initialize the process; called by thread_init or the process loader
 void mi_process_init(void) mi_attr_noexcept {
   // ensure we are called once
   if (_mi_process_is_initialized) return;
+  _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id());
   _mi_process_is_initialized = true;
   mi_process_setup_auto_thread_done();
 
-  _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id());
+  
+  mi_detect_cpu_features();
   _mi_os_init();
   mi_heap_main_init();
   #if (MI_DEBUG)
@@ -482,11 +578,30 @@ void mi_process_init(void) mi_attr_noexcept {
   #endif
   _mi_verbose_message("secure level: %d\n", MI_SECURE);
   mi_thread_init();
+
+  #if defined(_WIN32) && !defined(MI_SHARED_LIB)
+  // When building as a static lib the FLS cleanup happens to early for the main thread.
+  // To avoid this, set the FLS value for the main thread to NULL so the fls cleanup
+  // will not call _mi_thread_done on the (still executing) main thread. See issue #508.
+  FlsSetValue(mi_fls_key, NULL);
+  #endif
+
   mi_stats_reset();  // only call stat reset *after* thread init (or the heap tld == NULL)
 
   if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) {
-    size_t pages = mi_option_get(mi_option_reserve_huge_os_pages);
-    mi_reserve_huge_os_pages_interleave(pages, 0, pages*500);
+    size_t pages = mi_option_get_clamp(mi_option_reserve_huge_os_pages, 0, 128*1024);
+    long reserve_at = mi_option_get(mi_option_reserve_huge_os_pages_at);
+    if (reserve_at != -1) {
+      mi_reserve_huge_os_pages_at(pages, reserve_at, pages*500);
+    } else {
+      mi_reserve_huge_os_pages_interleave(pages, 0, pages*500);
+    }
+  } 
+  if (mi_option_is_enabled(mi_option_reserve_os_memory)) {
+    long ksize = mi_option_get(mi_option_reserve_os_memory);
+    if (ksize > 0) {
+      mi_reserve_os_memory((size_t)ksize*MI_KiB, true /* commit? */, true /* allow large pages? */);
+    }
   }
 }
 
@@ -500,15 +615,16 @@ static void mi_process_done(void) {
   process_done = true;
 
   #if defined(_WIN32) && !defined(MI_SHARED_LIB)
-  FlsSetValue(mi_fls_key, NULL);  // don't call main-thread callback
-  FlsFree(mi_fls_key);            // call thread-done on all threads to prevent dangling callback pointer if statically linked with a DLL; Issue #208
+  FlsFree(mi_fls_key);  // call thread-done on all threads (except the main thread) to prevent dangling callback pointer if statically linked with a DLL; Issue #208
   #endif
   
-  #if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB)  
-  // free all memory if possible on process exit. This is not needed for a stand-alone process
-  // but should be done if mimalloc is statically linked into another shared library which
-  // is repeatedly loaded/unloaded, see issue #281.
-  mi_collect(true /* force */ );
+  #ifndef MI_SKIP_COLLECT_ON_EXIT
+    #if (MI_DEBUG != 0) || !defined(MI_SHARED_LIB)  
+    // free all memory if possible on process exit. This is not needed for a stand-alone process
+    // but should be done if mimalloc is statically linked into another shared library which
+    // is repeatedly loaded/unloaded, see issue #281.
+    mi_collect(true /* force */ );
+    #endif
   #endif
 
   if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) {
@@ -524,31 +640,22 @@ static void mi_process_done(void) {
 #if defined(_WIN32) && defined(MI_SHARED_LIB)
   // Windows DLL: easy to hook into process_init and thread_done
   __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
-    UNUSED(reserved);
-    UNUSED(inst);
+    MI_UNUSED(reserved);
+    MI_UNUSED(inst);
     if (reason==DLL_PROCESS_ATTACH) {
       mi_process_load();
     }
-    else if (reason==DLL_THREAD_DETACH) {
-      if (!mi_is_redirected()) mi_thread_done();
+    else if (reason==DLL_PROCESS_DETACH) {
+      mi_process_done();
     }
+    else if (reason==DLL_THREAD_DETACH) {
+      if (!mi_is_redirected()) {
+        mi_thread_done();
+      }
+    }    
     return TRUE;
   }
 
-#elif defined(__cplusplus)
-  // C++: use static initialization to detect process start
-  static bool _mi_process_init(void) {
-    mi_process_load();
-    return (_mi_heap_main.thread_id != 0);
-  }
-  static bool mi_initialized = _mi_process_init();
-
-#elif defined(__GNUC__) || defined(__clang__)
-  // GCC,Clang: use the constructor attribute
-  static void __attribute__((constructor)) _mi_process_init(void) {
-    mi_process_load();
-  }
-
 #elif defined(_MSC_VER)
   // MSVC: use data section magic for static libraries
   // See <https://www.codeguru.com/cpp/misc/misc/applicationcontrol/article.php/c6945/Running-Code-Before-and-After-Main.htm>
@@ -556,17 +663,31 @@ static void mi_process_done(void) {
     mi_process_load();
     return 0;
   }
-  typedef int(*_crt_cb)(void);
-  #ifdef _M_X64
+  typedef int(*_mi_crt_callback_t)(void);
+  #if defined(_M_X64) || defined(_M_ARM64)
     __pragma(comment(linker, "/include:" "_mi_msvc_initu"))
     #pragma section(".CRT$XIU", long, read)
   #else
     __pragma(comment(linker, "/include:" "__mi_msvc_initu"))
   #endif
   #pragma data_seg(".CRT$XIU")
-  _crt_cb _mi_msvc_initu[] = { &_mi_process_init };
+  mi_decl_externc _mi_crt_callback_t _mi_msvc_initu[] = { &_mi_process_init };
   #pragma data_seg()
 
+#elif defined(__cplusplus)
+  // C++: use static initialization to detect process start
+  static bool _mi_process_init(void) {
+    mi_process_load();
+    return (_mi_heap_main.thread_id != 0);
+  }
+  static bool mi_initialized = _mi_process_init();
+
+#elif defined(__GNUC__) || defined(__clang__)
+  // GCC,Clang: use the constructor attribute
+  static void __attribute__((constructor)) _mi_process_init(void) {
+    mi_process_load();
+  }
+
 #else
 #pragma message("define a way to call mi_process_load on your platform")
 #endif
index f29b387c29ad4d8da2e061bddb1d4b6c3aabbf89..b07e0e77cbd89b3523808bb751b622ce5d238242 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -14,9 +14,15 @@ terms of the MIT license. A copy of the license can be found in the file
 #include <ctype.h>  // toupper
 #include <stdarg.h>
 
-static uintptr_t mi_max_error_count = 16;  // stop outputting errors after this
+#ifdef _MSC_VER
+#pragma warning(disable:4996)   // strncpy, strncat
+#endif
+
 
-static void mi_add_stderr_output();
+static long mi_max_error_count   = 16; // stop outputting errors after this (use < 0 for no limit)
+static long mi_max_warning_count = 16; // stop outputting warnings after this (use < 0 for no limit)
+
+static void mi_add_stderr_output(void);
 
 int mi_version(void) mi_attr_noexcept {
   return MI_MALLOC_VERSION;
@@ -43,46 +49,52 @@ typedef struct mi_option_desc_s {
   mi_init_t   init;   // is it initialized yet? (from the environment)
   mi_option_t option; // for debugging: the option index should match the option
   const char* name;   // option name without `mimalloc_` prefix
+  const char* legacy_name; // potential legacy v1.x option name
 } mi_option_desc_t;
 
-#define MI_OPTION(opt)        mi_option_##opt, #opt
-#define MI_OPTION_DESC(opt)   {0, UNINIT, MI_OPTION(opt) }
+#define MI_OPTION(opt)                  mi_option_##opt, #opt, NULL
+#define MI_OPTION_LEGACY(opt,legacy)    mi_option_##opt, #opt, #legacy
 
 static mi_option_desc_t options[_mi_option_last] =
 {
   // stable options
-#if MI_DEBUG || defined(MI_SHOW_ERRORS)
+  #if MI_DEBUG || defined(MI_SHOW_ERRORS)
   { 1, UNINIT, MI_OPTION(show_errors) },
-#else
+  #else
   { 0, UNINIT, MI_OPTION(show_errors) },
-#endif
+  #endif
   { 0, UNINIT, MI_OPTION(show_stats) },
   { 0, UNINIT, MI_OPTION(verbose) },
 
-  // the following options are experimental and not all combinations make sense.
-  { 1, UNINIT, MI_OPTION(eager_commit) },        // commit on demand
-  #if defined(_WIN32) || (MI_INTPTR_SIZE <= 4)   // and other OS's without overcommit?
-  { 0, UNINIT, MI_OPTION(eager_region_commit) },
-  { 1, UNINIT, MI_OPTION(reset_decommits) },     // reset decommits memory
-  #else
-  { 1, UNINIT, MI_OPTION(eager_region_commit) },
-  { 0, UNINIT, MI_OPTION(reset_decommits) },     // reset uses MADV_FREE/MADV_DONTNEED
-  #endif
+  // Some of the following options are experimental and not all combinations are valid. Use with care.
+  { 1, UNINIT, MI_OPTION(eager_commit) },        // commit per segment directly (8MiB)  (but see also `eager_commit_delay`)
+  { 0, UNINIT, MI_OPTION(deprecated_eager_region_commit) },
+  { 0, UNINIT, MI_OPTION(deprecated_reset_decommits) },
   { 0, UNINIT, MI_OPTION(large_os_pages) },      // use large OS pages, use only with eager commit to prevent fragmentation of VMA's
-  { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) },
-  { 0, UNINIT, MI_OPTION(segment_cache) },       // cache N segments per thread
-  { 1, UNINIT, MI_OPTION(page_reset) },          // reset page memory on free
-  { 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates
-  { 0, UNINIT, MI_OPTION(segment_reset) },       // reset segment memory on free (needs eager commit)
-#if defined(__NetBSD__)
+  { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) },  // per 1GiB huge pages
+  { -1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N
+  { 0, UNINIT, MI_OPTION(reserve_os_memory)     },
+  { 0, UNINIT, MI_OPTION(deprecated_segment_cache) },  // cache N segments per thread
+  { 0, UNINIT, MI_OPTION(page_reset) },          // reset page memory on free
+  { 0, UNINIT, MI_OPTION_LEGACY(abandoned_page_decommit, abandoned_page_reset) },// decommit free page memory when a thread terminates  
+  { 0, UNINIT, MI_OPTION(deprecated_segment_reset) },
+  #if defined(__NetBSD__)
   { 0, UNINIT, MI_OPTION(eager_commit_delay) },  // the first N segments per thread are not eagerly committed
-#else
-  { 1, UNINIT, MI_OPTION(eager_commit_delay) },  // the first N segments per thread are not eagerly committed
-#endif
-  { 100, UNINIT, MI_OPTION(reset_delay) },       // reset delay in milli-seconds
-  { 0,   UNINIT, MI_OPTION(use_numa_nodes) },    // 0 = use available numa nodes, otherwise use at most N nodes.
-  { 100, UNINIT, MI_OPTION(os_tag) },            // only apple specific for now but might serve more or less related purpose
-  { 16,  UNINIT, MI_OPTION(max_errors) }         // maximum errors that are output
+  #elif defined(_WIN32)
+  { 4, UNINIT, MI_OPTION(eager_commit_delay) },  // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
+  #else
+  { 1, UNINIT, MI_OPTION(eager_commit_delay) },  // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
+  #endif
+  { 25,   UNINIT, MI_OPTION_LEGACY(decommit_delay, reset_delay) }, // page decommit delay in milli-seconds
+  { 0,    UNINIT, MI_OPTION(use_numa_nodes) },    // 0 = use available numa nodes, otherwise use at most N nodes. 
+  { 0,    UNINIT, MI_OPTION(limit_os_alloc) },    // 1 = do not use OS memory for allocation (but only reserved arenas)
+  { 100,  UNINIT, MI_OPTION(os_tag) },            // only apple specific for now but might serve more or less related purpose
+  { 16,   UNINIT, MI_OPTION(max_errors) },        // maximum errors that are output
+  { 16,   UNINIT, MI_OPTION(max_warnings) },      // maximum warnings that are output
+  { 8,    UNINIT, MI_OPTION(max_segment_reclaim)},// max. number of segment reclaims from the abandoned segments per try.  
+  { 1,    UNINIT, MI_OPTION(allow_decommit) },    // decommit slices when no longer used (after decommit_delay milli-seconds)
+  { 500,  UNINIT, MI_OPTION(segment_decommit_delay) }, // decommit delay in milli-seconds for freed segments
+  { 2,    UNINIT, MI_OPTION(decommit_extend_delay) }
 };
 
 static void mi_option_init(mi_option_desc_t* desc);
@@ -93,17 +105,19 @@ void _mi_options_init(void) {
   mi_add_stderr_output(); // now it safe to use stderr for output
   for(int i = 0; i < _mi_option_last; i++ ) {
     mi_option_t option = (mi_option_t)i;
-    long l = mi_option_get(option); UNUSED(l); // initialize
+    long l = mi_option_get(option); MI_UNUSED(l); // initialize
     if (option != mi_option_verbose) {
       mi_option_desc_t* desc = &options[option];
       _mi_verbose_message("option '%s': %ld\n", desc->name, desc->value);
     }
   }
   mi_max_error_count = mi_option_get(mi_option_max_errors);
+  mi_max_warning_count = mi_option_get(mi_option_max_warnings);
 }
 
-long mi_option_get(mi_option_t option) {
+mi_decl_nodiscard long mi_option_get(mi_option_t option) {
   mi_assert(option >= 0 && option < _mi_option_last);
+  if (option < 0 || option >= _mi_option_last) return 0;
   mi_option_desc_t* desc = &options[option];
   mi_assert(desc->option == option);  // index should match the option
   if (mi_unlikely(desc->init == UNINIT)) {
@@ -112,8 +126,14 @@ long mi_option_get(mi_option_t option) {
   return desc->value;
 }
 
+mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long max) {
+  long x = mi_option_get(option);
+  return (x < min ? min : (x > max ? max : x));
+}
+
 void mi_option_set(mi_option_t option, long value) {
   mi_assert(option >= 0 && option < _mi_option_last);
+  if (option < 0 || option >= _mi_option_last) return;
   mi_option_desc_t* desc = &options[option];
   mi_assert(desc->option == option);  // index should match the option
   desc->value = value;
@@ -122,13 +142,14 @@ void mi_option_set(mi_option_t option, long value) {
 
 void mi_option_set_default(mi_option_t option, long value) {
   mi_assert(option >= 0 && option < _mi_option_last);
+  if (option < 0 || option >= _mi_option_last) return;
   mi_option_desc_t* desc = &options[option];
   if (desc->init != INITIALIZED) {
     desc->value = value;
   }
 }
 
-bool mi_option_is_enabled(mi_option_t option) {
+mi_decl_nodiscard bool mi_option_is_enabled(mi_option_t option) {
   return (mi_option_get(option) != 0);
 }
 
@@ -150,11 +171,23 @@ void mi_option_disable(mi_option_t option) {
 
 
 static void mi_out_stderr(const char* msg, void* arg) {
-  UNUSED(arg);
+  MI_UNUSED(arg);
+  if (msg == NULL) return;
   #ifdef _WIN32
   // on windows with redirection, the C runtime cannot handle locale dependent output
   // after the main thread closes so we use direct console output.
-  if (!_mi_preloading()) { _cputs(msg); }
+  if (!_mi_preloading()) { 
+    // _cputs(msg);  // _cputs cannot be used at is aborts if it fails to lock the console
+    static HANDLE hcon = INVALID_HANDLE_VALUE;
+    if (hcon == INVALID_HANDLE_VALUE) {
+      hcon = GetStdHandle(STD_ERROR_HANDLE);
+    }
+    const size_t len = strlen(msg);
+    if (hcon != INVALID_HANDLE_VALUE && len > 0 && len < UINT32_MAX) {
+      DWORD written = 0;
+      WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
+    }
+  }
   #else
   fputs(msg, stderr);
   #endif
@@ -165,31 +198,31 @@ static void mi_out_stderr(const char* msg, void* arg) {
 // an output function is registered it is called immediately with
 // the output up to that point.
 #ifndef MI_MAX_DELAY_OUTPUT
-#define MI_MAX_DELAY_OUTPUT (32*1024)
+#define MI_MAX_DELAY_OUTPUT ((size_t)(32*1024))
 #endif
 static char out_buf[MI_MAX_DELAY_OUTPUT+1];
-static _Atomic(uintptr_t) out_len;
+static _Atomic(size_t) out_len;
 
 static void mi_out_buf(const char* msg, void* arg) {
-  UNUSED(arg);
+  MI_UNUSED(arg);
   if (msg==NULL) return;
-  if (mi_atomic_read_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
+  if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
   size_t n = strlen(msg);
   if (n==0) return;
   // claim space
-  uintptr_t start = mi_atomic_add(&out_len, n);
+  size_t start = mi_atomic_add_acq_rel(&out_len, n);
   if (start >= MI_MAX_DELAY_OUTPUT) return;
   // check bound
   if (start+n >= MI_MAX_DELAY_OUTPUT) {
     n = MI_MAX_DELAY_OUTPUT-start-1;
   }
-  memcpy(&out_buf[start], msg, n);
+  _mi_memcpy(&out_buf[start], msg, n);
 }
 
 static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) {
   if (out==NULL) return;
   // claim (if `no_more_buf == true`, no more output will be added after this point)
-  size_t count = mi_atomic_add(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1));
+  size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1));
   // and output the current contents
   if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT;
   out_buf[count] = 0;
@@ -215,19 +248,18 @@ static void mi_out_buf_stderr(const char* msg, void* arg) {
 
 // Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t.
 // For now, don't register output from multiple threads.
-#pragma warning(suppress:4180)
 static mi_output_fun* volatile mi_out_default; // = NULL
-static volatile _Atomic(void*) mi_out_arg; // = NULL
+static _Atomic(void*) mi_out_arg; // = NULL
 
 static mi_output_fun* mi_out_get_default(void** parg) {
-  if (parg != NULL) { *parg = mi_atomic_read_ptr(void,&mi_out_arg); }
+  if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); }
   mi_output_fun* out = mi_out_default;
   return (out == NULL ? &mi_out_buf : out);
 }
 
 void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept {
   mi_out_default = (out == NULL ? &mi_out_stderr : out); // stop using the delayed output buffer
-  mi_atomic_write_ptr(void,&mi_out_arg, arg);
+  mi_atomic_store_ptr_release(void,&mi_out_arg, arg);
   if (out!=NULL) mi_out_buf_flush(out,true,arg);         // output all the delayed output now
 }
 
@@ -241,26 +273,42 @@ static void mi_add_stderr_output() {
 // --------------------------------------------------------
 // Messages, all end up calling `_mi_fputs`.
 // --------------------------------------------------------
-static volatile _Atomic(uintptr_t) error_count; // = 0;  // when MAX_ERROR_COUNT stop emitting errors and warnings
+static _Atomic(size_t) error_count;   // = 0;  // when >= max_error_count stop emitting errors
+static _Atomic(size_t) warning_count; // = 0;  // when >= max_warning_count stop emitting warnings
 
 // When overriding malloc, we may recurse into mi_vfprintf if an allocation
 // inside the C runtime causes another message.
+// In some cases (like on macOS) the loader already allocates which
+// calls into mimalloc; if we then access thread locals (like `recurse`)
+// this may crash as the access may call _tlv_bootstrap that tries to 
+// (recursively) invoke malloc again to allocate space for the thread local
+// variables on demand. This is why we use a _mi_preloading test on such
+// platforms. However, C code generator may move the initial thread local address
+// load before the `if` and we therefore split it out in a separate funcion.
 static mi_decl_thread bool recurse = false;
 
-static bool mi_recurse_enter(void) {
-  #ifdef MI_TLS_RECURSE_GUARD
-  if (_mi_preloading()) return true;
-  #endif
+static mi_decl_noinline bool mi_recurse_enter_prim(void) {
   if (recurse) return false;
   recurse = true;
   return true;
 }
 
+static mi_decl_noinline void mi_recurse_exit_prim(void) {
+  recurse = false;
+}
+
+static bool mi_recurse_enter(void) {
+  #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
+  if (_mi_preloading()) return true;
+  #endif
+  return mi_recurse_enter_prim();
+}
+
 static void mi_recurse_exit(void) {
-  #ifdef MI_TLS_RECURSE_GUARD
+  #if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
   if (_mi_preloading()) return;
   #endif
-  recurse = false;
+  mi_recurse_exit_prim();
 }
 
 void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) {
@@ -295,11 +343,22 @@ void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) {
   va_end(args);
 }
 
+static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) {
+  if (prefix != NULL && strlen(prefix) <= 32 && !_mi_is_main_thread()) {
+    char tprefix[64];
+    snprintf(tprefix, sizeof(tprefix), "%sthread 0x%zx: ", prefix, _mi_thread_id());
+    mi_vfprintf(out, arg, tprefix, fmt, args);
+  }
+  else {
+    mi_vfprintf(out, arg, prefix, fmt, args);
+  }
+}
+
 void _mi_trace_message(const char* fmt, ...) {
   if (mi_option_get(mi_option_verbose) <= 1) return;  // only with verbose level 2 or higher
   va_list args;
   va_start(args, fmt);
-  mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args);
+  mi_vfprintf_thread(NULL, NULL, "mimalloc: ", fmt, args);
   va_end(args);
 }
 
@@ -312,17 +371,21 @@ void _mi_verbose_message(const char* fmt, ...) {
 }
 
 static void mi_show_error_message(const char* fmt, va_list args) {
-  if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return;
-  if (mi_atomic_increment(&error_count) > mi_max_error_count) return;
-  mi_vfprintf(NULL, NULL, "mimalloc: error: ", fmt, args);
+  if (!mi_option_is_enabled(mi_option_verbose)) {
+    if (!mi_option_is_enabled(mi_option_show_errors)) return;
+    if (mi_max_error_count >= 0 && (long)mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return;
+  }
+  mi_vfprintf_thread(NULL, NULL, "mimalloc: error: ", fmt, args);
 }
 
 void _mi_warning_message(const char* fmt, ...) {
-  if (!mi_option_is_enabled(mi_option_show_errors) && !mi_option_is_enabled(mi_option_verbose)) return;
-  if (mi_atomic_increment(&error_count) > mi_max_error_count) return;
+  if (!mi_option_is_enabled(mi_option_verbose)) {
+    if (!mi_option_is_enabled(mi_option_show_errors)) return;
+    if (mi_max_warning_count >= 0 && (long)mi_atomic_increment_acq_rel(&warning_count) > mi_max_warning_count) return;
+  }
   va_list args;
   va_start(args,fmt);
-  mi_vfprintf(NULL, NULL, "mimalloc: warning: ", fmt, args);
+  mi_vfprintf_thread(NULL, NULL, "mimalloc: warning: ", fmt, args);
   va_end(args);
 }
 
@@ -339,10 +402,10 @@ void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, co
 // --------------------------------------------------------
 
 static mi_error_fun* volatile  mi_error_handler; // = NULL
-static volatile _Atomic(void*) mi_error_arg;     // = NULL
+static _Atomic(void*) mi_error_arg;     // = NULL
 
 static void mi_error_default(int err) {
-  UNUSED(err);
+  MI_UNUSED(err);
 #if (MI_DEBUG>0) 
   if (err==EFAULT) {
     #ifdef _MSC_VER
@@ -365,7 +428,7 @@ static void mi_error_default(int err) {
 
 void mi_register_error(mi_error_fun* fun, void* arg) {
   mi_error_handler = fun;  // can be NULL
-  mi_atomic_write_ptr(void,&mi_error_arg, arg);
+  mi_atomic_store_ptr_release(void,&mi_error_arg, arg);
 }
 
 void _mi_error_message(int err, const char* fmt, ...) {
@@ -376,7 +439,7 @@ void _mi_error_message(int err, const char* fmt, ...) {
   va_end(args);
   // and call the error handler which may abort (or return normally)
   if (mi_error_handler != NULL) {
-    mi_error_handler(err, mi_atomic_read_ptr(void,&mi_error_arg));
+    mi_error_handler(err, mi_atomic_load_ptr_acquire(void,&mi_error_arg));
   }
   else {
     mi_error_default(err);
@@ -388,18 +451,35 @@ void _mi_error_message(int err, const char* fmt, ...) {
 // --------------------------------------------------------
 
 static void mi_strlcpy(char* dest, const char* src, size_t dest_size) {
-  dest[0] = 0;
-  #pragma warning(suppress:4996)
-  strncpy(dest, src, dest_size - 1);
-  dest[dest_size - 1] = 0;
+  if (dest==NULL || src==NULL || dest_size == 0) return;
+  // copy until end of src, or when dest is (almost) full
+  while (*src != 0 && dest_size > 1) {
+    *dest++ = *src++;
+    dest_size--;
+  }
+  // always zero terminate
+  *dest = 0;
 }
 
 static void mi_strlcat(char* dest, const char* src, size_t dest_size) {
-  #pragma warning(suppress:4996)
-  strncat(dest, src, dest_size - 1);
-  dest[dest_size - 1] = 0;
+  if (dest==NULL || src==NULL || dest_size == 0) return;
+  // find end of string in the dest buffer
+  while (*dest != 0 && dest_size > 1) {
+    dest++;
+    dest_size--;
+  }
+  // and catenate
+  mi_strlcpy(dest, src, dest_size);
 }
 
+#ifdef MI_NO_GETENV
+static bool mi_getenv(const char* name, char* result, size_t result_size) {
+  MI_UNUSED(name);
+  MI_UNUSED(result);
+  MI_UNUSED(result_size);
+  return false;
+}
+#else
 static inline int mi_strnicmp(const char* s, const char* t, size_t n) {
   if (n==0) return 0;
   for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) {
@@ -407,7 +487,6 @@ static inline int mi_strnicmp(const char* s, const char* t, size_t n) {
   }
   return (n==0 ? 0 : *s - *t);
 }
-
 #if defined _WIN32
 // On Windows use GetEnvironmentVariable instead of getenv to work
 // reliably even when this is invoked before the C runtime is initialized.
@@ -422,7 +501,7 @@ static bool mi_getenv(const char* name, char* result, size_t result_size) {
 #elif !defined(MI_USE_ENVIRON) || (MI_USE_ENVIRON!=0)
 // On Posix systemsr use `environ` to acces environment variables 
 // even before the C runtime is initialized.
-#if defined(__APPLE__)
+#if defined(__APPLE__) && defined(__has_include) && __has_include(<crt_externs.h>)
 #include <crt_externs.h>
 static char** mi_get_environ(void) {
   return (*_NSGetEnviron());
@@ -475,15 +554,26 @@ static bool mi_getenv(const char* name, char* result, size_t result_size) {
     return false;
   }
 }
-#endif
+#endif  // !MI_USE_ENVIRON
+#endif  // !MI_NO_GETENV
 
 static void mi_option_init(mi_option_desc_t* desc) {  
   // Read option value from the environment
+  char s[64+1];
   char buf[64+1];
   mi_strlcpy(buf, "mimalloc_", sizeof(buf));
   mi_strlcat(buf, desc->name, sizeof(buf));
-  char s[64+1];
-  if (mi_getenv(buf, s, sizeof(s))) {
+  bool found = mi_getenv(buf,s,sizeof(s));
+  if (!found && desc->legacy_name != NULL) {
+    mi_strlcpy(buf, "mimalloc_", sizeof(buf));
+    mi_strlcat(buf, desc->legacy_name, sizeof(buf));
+    found = mi_getenv(buf,s,sizeof(s));
+    if (found) {
+      _mi_warning_message("environment option \"mimalloc_%s\" is deprecated -- use \"mimalloc_%s\" instead.\n", desc->legacy_name, desc->name );
+    }    
+  }
+
+  if (found) {
     size_t len = strlen(s);
     if (len >= sizeof(buf)) len = sizeof(buf) - 1;
     for (size_t i = 0; i < len; i++) {
@@ -501,13 +591,32 @@ static void mi_option_init(mi_option_desc_t* desc) {
     else {
       char* end = buf;
       long value = strtol(buf, &end, 10);
+      if (desc->option == mi_option_reserve_os_memory) {
+        // this option is interpreted in KiB to prevent overflow of `long`
+        if (*end == 'K') { end++; }
+        else if (*end == 'M') { value *= MI_KiB; end++; }
+        else if (*end == 'G') { value *= MI_MiB; end++; }
+        else { value = (value + MI_KiB - 1) / MI_KiB; }
+        if (end[0] == 'I' && end[1] == 'B') { end += 2; }
+        else if (*end == 'B') { end++; }
+      }
       if (*end == 0) {
         desc->value = value;
         desc->init = INITIALIZED;
       }
       else {
-        _mi_warning_message("environment option mimalloc_%s has an invalid value: %s\n", desc->name, buf);
+        // set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose.
         desc->init = DEFAULTED;
+        if (desc->option == mi_option_verbose && desc->value == 0) {
+          // if the 'mimalloc_verbose' env var has a bogus value we'd never know
+          // (since the value defaults to 'off') so in that case briefly enable verbose
+          desc->value = 1;
+          _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name );
+          desc->value = 0;
+        }
+        else {
+          _mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name );
+        }
       }
     }
     mi_assert_internal(desc->init != UNINIT);
index fe30cf43283b3d09ebbc7b37b4a4040de623dfd4..72959d8185739ecbd8773cfac8299ba991e33c2f 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -22,16 +22,24 @@ terms of the MIT license. A copy of the license can be found in the file
 
 #include <string.h>  // strerror
 
+#ifdef _MSC_VER
+#pragma warning(disable:4996)  // strerror
+#endif
+
+#if defined(__wasi__)
+#define MI_USE_SBRK
+#endif
 
 #if defined(_WIN32)
 #include <windows.h>
 #elif defined(__wasi__)
-// stdlib.h is all we need, and has already been included in mimalloc.h
+#include <unistd.h>    // sbrk
 #else
 #include <sys/mman.h>  // mmap
 #include <unistd.h>    // sysconf
 #if defined(__linux__)
 #include <features.h>
+#include <fcntl.h>
 #if defined(__GLIBC__)
 #include <linux/mman.h> // linux mmap flags
 #else
@@ -44,9 +52,13 @@ terms of the MIT license. A copy of the license can be found in the file
 #include <mach/vm_statistics.h>
 #endif
 #endif
-#if defined(__HAIKU__)
-#define madvise posix_madvise
-#define MADV_DONTNEED POSIX_MADV_DONTNEED
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#if __FreeBSD_version >= 1200000
+#include <sys/cpuset.h>
+#include <sys/domainset.h>
+#endif
+#include <sys/sysctl.h>
 #endif
 #endif
 
@@ -55,20 +67,18 @@ terms of the MIT license. A copy of the license can be found in the file
   On windows initializes support for aligned allocation and
   large OS pages (if MIMALLOC_LARGE_OS_PAGES is true).
 ----------------------------------------------------------- */
-bool    _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
+bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
+bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats);
 
 static void* mi_align_up_ptr(void* p, size_t alignment) {
   return (void*)_mi_align_up((uintptr_t)p, alignment);
 }
 
-static uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) {
-  return (sz / alignment) * alignment;
-}
-
 static void* mi_align_down_ptr(void* p, size_t alignment) {
   return (void*)_mi_align_down((uintptr_t)p, alignment);
 }
 
+
 // page size (initialized properly in `os_init`)
 static size_t os_page_size = 4096;
 
@@ -78,31 +88,41 @@ static size_t os_alloc_granularity = 4096;
 // if non-zero, use large page allocation
 static size_t large_os_page_size = 0;
 
+// is memory overcommit allowed? 
+// set dynamically in _mi_os_init (and if true we use MAP_NORESERVE)
+static bool os_overcommit = true;
+
+bool _mi_os_has_overcommit(void) {
+  return os_overcommit;
+}
+
 // OS (small) page size
-size_t _mi_os_page_size() {
+size_t _mi_os_page_size(void) {
   return os_page_size;
 }
 
 // if large OS pages are supported (2 or 4MiB), then return the size, otherwise return the small page size (4KiB)
-size_t _mi_os_large_page_size() {
+size_t _mi_os_large_page_size(void) {
   return (large_os_page_size != 0 ? large_os_page_size : _mi_os_page_size());
 }
 
+#if !defined(MI_USE_SBRK) && !defined(__wasi__)
 static bool use_large_os_page(size_t size, size_t alignment) {
   // if we have access, check the size and alignment requirements
   if (large_os_page_size == 0 || !mi_option_is_enabled(mi_option_large_os_pages)) return false;
   return ((size % large_os_page_size) == 0 && (alignment % large_os_page_size) == 0);
 }
+#endif
 
 // round to a good OS allocation size (bounded by max 12.5% waste)
 size_t _mi_os_good_alloc_size(size_t size) {
   size_t align_size;
-  if (size < 512*KiB) align_size = _mi_os_page_size();
-  else if (size < 2*MiB) align_size = 64*KiB;
-  else if (size < 8*MiB) align_size = 256*KiB;
-  else if (size < 32*MiB) align_size = 1*MiB;
-  else align_size = 4*MiB;
-  if (size >= (SIZE_MAX - align_size)) return size; // possible overflow?
+  if (size < 512*MI_KiB) align_size = _mi_os_page_size();
+  else if (size < 2*MI_MiB) align_size = 64*MI_KiB;
+  else if (size < 8*MI_MiB) align_size = 256*MI_KiB;
+  else if (size < 32*MI_MiB) align_size = 1*MI_MiB;
+  else align_size = 4*MI_MiB;
+  if (mi_unlikely(size >= (SIZE_MAX - align_size))) return size; // possible overflow?
   return _mi_align_up(size, align_size);
 }
 
@@ -110,26 +130,47 @@ size_t _mi_os_good_alloc_size(size_t size) {
 // We use VirtualAlloc2 for aligned allocation, but it is only supported on Windows 10 and Windows Server 2016.
 // So, we need to look it up dynamically to run on older systems. (use __stdcall for 32-bit compatibility)
 // NtAllocateVirtualAllocEx is used for huge OS page allocation (1GiB)
-//
-// We hide MEM_EXTENDED_PARAMETER to compile with older SDK's.
+// We define a minimal MEM_EXTENDED_PARAMETER ourselves in order to be able to compile with older SDK's.
+typedef enum MI_MEM_EXTENDED_PARAMETER_TYPE_E {
+  MiMemExtendedParameterInvalidType = 0,
+  MiMemExtendedParameterAddressRequirements,
+  MiMemExtendedParameterNumaNode,
+  MiMemExtendedParameterPartitionHandle,
+  MiMemExtendedParameterUserPhysicalHandle,
+  MiMemExtendedParameterAttributeFlags,
+  MiMemExtendedParameterMax
+} MI_MEM_EXTENDED_PARAMETER_TYPE; 
+
+typedef struct DECLSPEC_ALIGN(8) MI_MEM_EXTENDED_PARAMETER_S {
+  struct { DWORD64 Type : 8; DWORD64 Reserved : 56; } Type;
+  union  { DWORD64 ULong64; PVOID Pointer; SIZE_T Size; HANDLE Handle; DWORD ULong; } Arg;
+} MI_MEM_EXTENDED_PARAMETER;
+
+typedef struct MI_MEM_ADDRESS_REQUIREMENTS_S {
+  PVOID  LowestStartingAddress;
+  PVOID  HighestEndingAddress;
+  SIZE_T Alignment;
+} MI_MEM_ADDRESS_REQUIREMENTS;
+
+#define MI_MEM_EXTENDED_PARAMETER_NONPAGED_HUGE   0x00000010
+
 #include <winternl.h>
-typedef PVOID    (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ void*, ULONG);
-typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, /* MEM_EXTENDED_PARAMETER* */ PVOID, ULONG);
+typedef PVOID    (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
+typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
 static PVirtualAlloc2 pVirtualAlloc2 = NULL;
 static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
 
 // Similarly, GetNumaProcesorNodeEx is only supported since Windows 7
-#if (_WIN32_WINNT < 0x601)  // before Win7
-typedef struct _PROCESSOR_NUMBER { WORD Group; BYTE Number; BYTE Reserved; } PROCESSOR_NUMBER, *PPROCESSOR_NUMBER;
-#endif
-typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(PPROCESSOR_NUMBER ProcNumber);
-typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(PPROCESSOR_NUMBER Processor, PUSHORT NodeNumber);
+typedef struct MI_PROCESSOR_NUMBER_S { WORD Group; BYTE Number; BYTE Reserved; } MI_PROCESSOR_NUMBER;
+
+typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(MI_PROCESSOR_NUMBER* ProcNumber);
+typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(MI_PROCESSOR_NUMBER* Processor, PUSHORT NodeNumber);
 typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask);
 static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL;
 static PGetNumaProcessorNodeEx      pGetNumaProcessorNodeEx = NULL;
 static PGetNumaNodeProcessorMaskEx  pGetNumaNodeProcessorMaskEx = NULL;
 
-static bool mi_win_enable_large_os_pages()
+static bool mi_win_enable_large_os_pages(void)
 {
   if (large_os_page_size > 0) return true;
 
@@ -164,7 +205,9 @@ static bool mi_win_enable_large_os_pages()
   return (ok!=0);
 }
 
-void _mi_os_init(void) {
+void _mi_os_init(void) 
+{
+  os_overcommit = false;
   // get the page size
   SYSTEM_INFO si;
   GetSystemInfo(&si);
@@ -198,94 +241,201 @@ void _mi_os_init(void) {
   }
 }
 #elif defined(__wasi__)
-void _mi_os_init() {
-  os_page_size = 0x10000; // WebAssembly has a fixed page size: 64KB
+void _mi_os_init(void) {
+  os_overcommit = false;
+  os_page_size = 64*MI_KiB; // WebAssembly has a fixed page size: 64KiB
   os_alloc_granularity = 16;
 }
+
+#else  // generic unix
+
+static void os_detect_overcommit(void) {
+#if defined(__linux__)
+  int fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
+       if (fd < 0) return;
+  char buf[32];
+  ssize_t nread = read(fd, &buf, sizeof(buf));
+       close(fd);
+  // <https://www.kernel.org/doc/Documentation/vm/overcommit-accounting>
+  // 0: heuristic overcommit, 1: always overcommit, 2: never overcommit (ignore NORESERVE)
+  if (nread >= 1) {
+    os_overcommit = (buf[0] == '0' || buf[0] == '1');
+  }
+#elif defined(__FreeBSD__)
+  int val = 0;
+  size_t olen = sizeof(val);
+  if (sysctlbyname("vm.overcommit", &val, &olen, NULL, 0) == 0) {
+    os_overcommit = (val != 0);
+  }  
 #else
-void _mi_os_init() {
+  // default: overcommit is true  
+#endif
+}
+
+void _mi_os_init(void) {
   // get the page size
   long result = sysconf(_SC_PAGESIZE);
   if (result > 0) {
     os_page_size = (size_t)result;
     os_alloc_granularity = os_page_size;
   }
-  large_os_page_size = 2*MiB; // TODO: can we query the OS for this?
+  large_os_page_size = 2*MI_MiB; // TODO: can we query the OS for this?
+  os_detect_overcommit();
+}
+#endif
+
+
+#if defined(MADV_NORMAL)
+static int mi_madvise(void* addr, size_t length, int advice) {
+  #if defined(__sun)
+  return madvise((caddr_t)addr, length, advice);  // Solaris needs cast (issue #520)
+  #else
+  return madvise(addr, length, advice);
+  #endif
 }
 #endif
 
 
 /* -----------------------------------------------------------
-  Raw allocation on Windows (VirtualAlloc) and Unix's (mmap).
------------------------------------------------------------ */
+  aligned hinting
+-------------------------------------------------------------- */
+
+// On 64-bit systems, we can do efficient aligned allocation by using
+// the 2TiB to 30TiB area to allocate those.
+#if (MI_INTPTR_SIZE >= 8)
+static mi_decl_cache_align _Atomic(uintptr_t)aligned_base;
+
+// Return a MI_SEGMENT_SIZE aligned address that is probably available.
+// If this returns NULL, the OS will determine the address but on some OS's that may not be 
+// properly aligned which can be more costly as it needs to be adjusted afterwards.
+// For a size > 1GiB this always returns NULL in order to guarantee good ASLR randomization; 
+// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses 
+//  in the middle of the 2TiB - 6TiB address range (see issue #372))
+
+#define MI_HINT_BASE ((uintptr_t)2 << 40)  // 2TiB start
+#define MI_HINT_AREA ((uintptr_t)4 << 40)  // upto 6TiB   (since before win8 there is "only" 8TiB available to processes)
+#define MI_HINT_MAX  ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
+
+static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size)
+{
+  if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL;
+  size = _mi_align_up(size, MI_SEGMENT_SIZE);
+  if (size > 1*MI_GiB) return NULL;  // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096.
+  #if (MI_SECURE>0)
+  size += MI_SEGMENT_SIZE;        // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
+  #endif
+
+  uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
+  if (hint == 0 || hint > MI_HINT_MAX) {   // wrap or initialize
+    uintptr_t init = MI_HINT_BASE;
+    #if (MI_SECURE>0 || MI_DEBUG==0)       // security: randomize start of aligned allocations unless in debug mode
+    uintptr_t r = _mi_heap_random_next(mi_get_default_heap());
+    init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA);  // (randomly 20 bits)*4MiB == 0 to 4TiB
+    #endif
+    uintptr_t expected = hint + size;
+    mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init);
+    hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
+  }
+  if (hint%try_alignment != 0) return NULL;
+  return (void*)hint;
+}
+#else
+static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
+  MI_UNUSED(try_alignment); MI_UNUSED(size);
+  return NULL;
+}
+#endif
+
+/* -----------------------------------------------------------
+  Free memory
+-------------------------------------------------------------- */
 
 static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats)
 {
   if (addr == NULL || size == 0) return true; // || _mi_os_is_huge_reserved(addr)
   bool err = false;
 #if defined(_WIN32)
+  DWORD errcode = 0;
   err = (VirtualFree(addr, 0, MEM_RELEASE) == 0);
-#elif defined(__wasi__)
-  err = 0; // WebAssembly's heap cannot be shrunk
+  if (err) { errcode = GetLastError(); }
+  if (errcode == ERROR_INVALID_ADDRESS) {
+    // In mi_os_mem_alloc_aligned the fallback path may have returned a pointer inside
+    // the memory region returned by VirtualAlloc; in that case we need to free using
+    // the start of the region.
+    MEMORY_BASIC_INFORMATION info = { 0, 0 };
+    VirtualQuery(addr, &info, sizeof(info));
+    if (info.AllocationBase < addr && ((uint8_t*)addr - (uint8_t*)info.AllocationBase) < MI_SEGMENT_SIZE) {
+      errcode = 0;
+      err = (VirtualFree(info.AllocationBase, 0, MEM_RELEASE) == 0);
+      if (err) { errcode = GetLastError(); }
+    }
+  }
+  if (errcode != 0) {
+    _mi_warning_message("unable to release OS memory: error code 0x%x, addr: %p, size: %zu\n", errcode, addr, size);
+  }
+#elif defined(MI_USE_SBRK) || defined(__wasi__)
+  err = false; // sbrk heap cannot be shrunk
 #else
   err = (munmap(addr, size) == -1);
-#endif
-  if (was_committed) _mi_stat_decrease(&stats->committed, size);
-  _mi_stat_decrease(&stats->reserved, size);
   if (err) {
-    #pragma warning(suppress:4996)
-    _mi_warning_message("munmap failed: %s, addr 0x%8li, size %lu\n", strerror(errno), (size_t)addr, size);
-    return false;
-  }
-  else {
-    return true;
+    _mi_warning_message("unable to release OS memory: %s, addr: %p, size: %zu\n", strerror(errno), addr, size);
   }
+#endif
+  if (was_committed) { _mi_stat_decrease(&stats->committed, size); }
+  _mi_stat_decrease(&stats->reserved, size);
+  return !err;  
 }
 
-static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size);
+
+/* -----------------------------------------------------------
+  Raw allocation on Windows (VirtualAlloc) 
+-------------------------------------------------------------- */
 
 #ifdef _WIN32
+#define MEM_COMMIT_RESERVE  (MEM_COMMIT|MEM_RESERVE)
+
 static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) {
 #if (MI_INTPTR_SIZE >= 8)
-  // on 64-bit systems, try to use the virtual address area after 4TiB for 4MiB aligned allocations
-  void* hint;
-  if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment,size)) != NULL) {
-    void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE);
-    if (p != NULL) return p;
-    DWORD err = GetLastError();
-    if (err != ERROR_INVALID_ADDRESS &&   // If linked with multiple instances, we may have tried to allocate at an already allocated area (#210)
-        err != ERROR_INVALID_PARAMETER) { // Windows7 instability (#230)
-      return NULL;
+  // on 64-bit systems, try to use the virtual address area after 2TiB for 4MiB aligned allocations
+  if (addr == NULL) {
+    void* hint = mi_os_get_aligned_hint(try_alignment,size);
+    if (hint != NULL) {
+      void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE);
+      if (p != NULL) return p;
+      _mi_verbose_message("warning: unable to allocate hinted aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), hint, try_alignment, flags);
+      // fall through on error
     }
-    // fall through
   } 
 #endif
-#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
   // on modern Windows try use VirtualAlloc2 for aligned allocation
-  if (try_alignment > 0 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) {
-    MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 };
+  if (try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) {
+    MI_MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 };
     reqs.Alignment = try_alignment;
-    MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} };
-    param.Type = MemExtendedParameterAddressRequirements;
-    param.Pointer = &reqs;
-    return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, &param, 1);
+    MI_MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} };
+    param.Type.Type = MiMemExtendedParameterAddressRequirements;
+    param.Arg.Pointer = &reqs;
+    void* p = (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, &param, 1);
+    if (p != NULL) return p;
+    _mi_warning_message("unable to allocate aligned OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x)\n", size, GetLastError(), addr, try_alignment, flags);
+    // fall through on error
   }
-#endif
   // last resort
   return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
 }
 
 static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DWORD flags, bool large_only, bool allow_large, bool* is_large) {
   mi_assert_internal(!(large_only && !allow_large));
-  static volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
+  static _Atomic(size_t) large_page_try_ok; // = 0;
   void* p = NULL;
+  // Try to allocate large OS pages (2MiB) if allowed or required.
   if ((large_only || use_large_os_page(size, try_alignment))
       && allow_large && (flags&MEM_COMMIT)!=0 && (flags&MEM_RESERVE)!=0) {
-    uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
+    size_t try_ok = mi_atomic_load_acquire(&large_page_try_ok);
     if (!large_only && try_ok > 0) {
       // if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive.
       // therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times.
-      mi_atomic_cas_weak(&large_page_try_ok, try_ok - 1, try_ok);
+      mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1);
     }
     else {
       // large OS pages must always reserve and commit.
@@ -294,53 +444,150 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment,
       if (large_only) return p;
       // fall back to non-large page allocation on error (`p == NULL`).
       if (p == NULL) {
-        mi_atomic_write(&large_page_try_ok,10);  // on error, don't try again for the next N allocations
+        mi_atomic_store_release(&large_page_try_ok,10UL);  // on error, don't try again for the next N allocations
       }
     }
   }
+  // Fall back to regular page allocation
   if (p == NULL) {
     *is_large = ((flags&MEM_LARGE_PAGES) != 0);
     p = mi_win_virtual_allocx(addr, size, try_alignment, flags);
   }
   if (p == NULL) {
-    _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, GetLastError(), addr, large_only, allow_large);
+    _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: 0x%x, address: %p, alignment: %zu, flags: 0x%x, large only: %d, allow large: %d)\n", size, GetLastError(), addr, try_alignment, flags, large_only, allow_large);
   }
   return p;
 }
 
+/* -----------------------------------------------------------
+  Raw allocation using `sbrk` or `wasm_memory_grow`
+-------------------------------------------------------------- */
+
+#elif defined(MI_USE_SBRK) || defined(__wasi__)
+#if defined(MI_USE_SBRK) 
+  static void* mi_memory_grow( size_t size ) {
+    void* p = sbrk(size);
+    if (p == (void*)(-1)) return NULL;
+    #if !defined(__wasi__) // on wasi this is always zero initialized already (?)
+    memset(p,0,size); 
+    #endif
+    return p;
+  }
 #elif defined(__wasi__)
-static void* mi_wasm_heap_grow(size_t size, size_t try_alignment) {
-  uintptr_t base = __builtin_wasm_memory_size(0) * _mi_os_page_size();
-  uintptr_t aligned_base = _mi_align_up(base, (uintptr_t) try_alignment);
-  size_t alloc_size = _mi_align_up( aligned_base - base + size, _mi_os_page_size());
-  mi_assert(alloc_size >= size && (alloc_size % _mi_os_page_size()) == 0);
-  if (alloc_size < size) return NULL;
-  if (__builtin_wasm_memory_grow(0, alloc_size / _mi_os_page_size()) == SIZE_MAX) {
+  static void* mi_memory_grow( size_t size ) {
+    size_t base = (size > 0 ? __builtin_wasm_memory_grow(0,_mi_divide_up(size, _mi_os_page_size()))
+                            : __builtin_wasm_memory_size(0));
+    if (base == SIZE_MAX) return NULL;     
+    return (void*)(base * _mi_os_page_size());    
+  }
+#endif
+
+#if defined(MI_USE_PTHREADS)
+static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static void* mi_heap_grow(size_t size, size_t try_alignment) {
+  void* p = NULL;
+  if (try_alignment <= 1) {
+    // `sbrk` is not thread safe in general so try to protect it (we could skip this on WASM but leave it in for now)
+    #if defined(MI_USE_PTHREADS) 
+    pthread_mutex_lock(&mi_heap_grow_mutex);
+    #endif
+    p = mi_memory_grow(size);
+    #if defined(MI_USE_PTHREADS)
+    pthread_mutex_unlock(&mi_heap_grow_mutex);
+    #endif
+  }
+  else {
+    void* base = NULL;
+    size_t alloc_size = 0;
+    // to allocate aligned use a lock to try to avoid thread interaction
+    // between getting the current size and actual allocation
+    // (also, `sbrk` is not thread safe in general)
+    #if defined(MI_USE_PTHREADS)
+    pthread_mutex_lock(&mi_heap_grow_mutex);
+    #endif
+    {
+      void* current = mi_memory_grow(0);  // get current size
+      if (current != NULL) {
+        void* aligned_current = mi_align_up_ptr(current, try_alignment);  // and align from there to minimize wasted space
+        alloc_size = _mi_align_up( ((uint8_t*)aligned_current - (uint8_t*)current) + size, _mi_os_page_size());
+        base = mi_memory_grow(alloc_size);        
+      }
+    }
+    #if defined(MI_USE_PTHREADS)
+    pthread_mutex_unlock(&mi_heap_grow_mutex);
+    #endif
+    if (base != NULL) {
+      p = mi_align_up_ptr(base, try_alignment);
+      if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
+        // another thread used wasm_memory_grow/sbrk in-between and we do not have enough
+        // space after alignment. Give up (and waste the space as we cannot shrink :-( )
+        // (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align)
+        p = NULL;
+      }
+    }
+  }
+  if (p == NULL) {
+    _mi_warning_message("unable to allocate sbrk/wasm_memory_grow OS memory (%zu bytes, %zu alignment)\n", size, try_alignment);    
     errno = ENOMEM;
     return NULL;
   }
-  return (void*)aligned_base;
+  mi_assert_internal( try_alignment == 0 || (uintptr_t)p % try_alignment == 0 );
+  return p;
 }
-#else
+
+/* -----------------------------------------------------------
+  Raw allocation on Unix's (mmap)
+-------------------------------------------------------------- */
+#else 
 #define MI_OS_USE_MMAP
 static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int protect_flags, int flags, int fd) {
-  void* p = NULL;
-  #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
-  // on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations
-  void* hint;
-  if (addr == NULL && (hint = mi_os_get_aligned_hint(try_alignment, size)) != NULL) {
-    p = mmap(hint,size,protect_flags,flags,fd,0);
-    if (p==MAP_FAILED) p = NULL; // fall back to regular mmap
+  MI_UNUSED(try_alignment);  
+  #if defined(MAP_ALIGNED)  // BSD
+  if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) {
+    size_t n = mi_bsr(try_alignment);
+    if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) {  // alignment is a power of 2 and 4096 <= alignment <= 1GiB
+      flags |= MAP_ALIGNED(n);
+      void* p = mmap(addr, size, protect_flags, flags | MAP_ALIGNED(n), fd, 0);
+      if (p!=MAP_FAILED) return p;
+      // fall back to regular mmap
+    }
+  }
+  #elif defined(MAP_ALIGN)  // Solaris
+  if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0) {
+    void* p = mmap((void*)try_alignment, size, protect_flags, flags | MAP_ALIGN, fd, 0);  // addr parameter is the required alignment
+    if (p!=MAP_FAILED) return p;
+    // fall back to regular mmap
   }
-  #else
-  UNUSED(try_alignment);
-  UNUSED(mi_os_get_aligned_hint);
   #endif
-  if (p==NULL) {
-    p = mmap(addr,size,protect_flags,flags,fd,0);
-    if (p==MAP_FAILED) p = NULL;
+  #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED)
+  // on 64-bit systems, use the virtual address area after 2TiB for 4MiB aligned allocations
+  if (addr == NULL) {
+    void* hint = mi_os_get_aligned_hint(try_alignment, size);
+    if (hint != NULL) {
+      void* p = mmap(hint, size, protect_flags, flags, fd, 0);
+      if (p!=MAP_FAILED) return p;
+      // fall back to regular mmap
+    }
   }
-  return p;
+  #endif
+  // regular mmap
+  void* p = mmap(addr, size, protect_flags, flags, fd, 0);
+  if (p!=MAP_FAILED) return p;  
+  // failed to allocate
+  return NULL;
+}
+
+static int mi_unix_mmap_fd(void) {
+#if defined(VM_MAKE_TAG)
+  // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99)
+  int os_tag = (int)mi_option_get(mi_option_os_tag);
+  if (os_tag < 100 || os_tag > 255) os_tag = 100;
+  return VM_MAKE_TAG(os_tag);
+#else
+  return -1;
+#endif
 }
 
 static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int protect_flags, bool large_only, bool allow_large, bool* is_large) {
@@ -351,34 +598,24 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
   #if !defined(MAP_NORESERVE)
   #define MAP_NORESERVE  0
   #endif
-  int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
-  int fd = -1;
-  #if defined(MAP_ALIGNED)  // BSD
-  if (try_alignment > 0) {
-    size_t n = _mi_bsr(try_alignment);
-    if (((size_t)1 << n) == try_alignment && n >= 12 && n <= 30) {  // alignment is a power of 2 and 4096 <= alignment <= 1GiB
-      flags |= MAP_ALIGNED(n);
-    }
-  }
-  #endif
+  const int fd = mi_unix_mmap_fd();
+  int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+  if (_mi_os_has_overcommit()) {
+    flags |= MAP_NORESERVE;
+  }  
   #if defined(PROT_MAX)
   protect_flags |= PROT_MAX(PROT_READ | PROT_WRITE); // BSD
-  #endif
-  #if defined(VM_MAKE_TAG)
-  // macOS: tracking anonymous page with a specific ID. (All up to 98 are taken officially but LLVM sanitizers had taken 99)
-  int os_tag = (int)mi_option_get(mi_option_os_tag);
-  if (os_tag < 100 || os_tag > 255) os_tag = 100;
-  fd = VM_MAKE_TAG(os_tag);
-  #endif
+  #endif    
+  // huge page allocation
   if ((large_only || use_large_os_page(size, try_alignment)) && allow_large) {
-    static volatile _Atomic(uintptr_t) large_page_try_ok; // = 0;
-    uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
+    static _Atomic(size_t) large_page_try_ok; // = 0;
+    size_t try_ok = mi_atomic_load_acquire(&large_page_try_ok);
     if (!large_only && try_ok > 0) {
       // If the OS is not configured for large OS pages, or the user does not have
       // enough permission, the `mmap` will always fail (but it might also fail for other reasons).
       // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times
       // to avoid too many failing calls to mmap.
-      mi_atomic_cas_weak(&large_page_try_ok, try_ok - 1, try_ok);
+      mi_atomic_cas_strong_acq_rel(&large_page_try_ok, &try_ok, try_ok - 1);
     }
     else {
       int lflags = flags & ~MAP_NORESERVE;  // using NORESERVE on huge pages seems to fail on Linux
@@ -391,7 +628,7 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
       #endif
       #ifdef MAP_HUGE_1GB
       static bool mi_huge_pages_available = true;
-      if ((size % GiB) == 0 && mi_huge_pages_available) {
+      if ((size % MI_GiB) == 0 && mi_huge_pages_available) {
         lflags |= MAP_HUGE_1GB;
       }
       else
@@ -418,37 +655,39 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
         #endif
         if (large_only) return p;
         if (p == NULL) {
-          mi_atomic_write(&large_page_try_ok, 10);  // on error, don't try again for the next N allocations
+          mi_atomic_store_release(&large_page_try_ok, (size_t)8);  // on error, don't try again for the next N allocations
         }
       }
     }
   }
+  // regular allocation
   if (p == NULL) {
     *is_large = false;
     p = mi_unix_mmapx(addr, size, try_alignment, protect_flags, flags, fd);
-    #if defined(MADV_HUGEPAGE)
-    // Many Linux systems don't allow MAP_HUGETLB but they support instead
-    // transparent huge pages (THP). It is not required to call `madvise` with MADV_HUGE
-    // though since properly aligned allocations will already use large pages if available
-    // in that case -- in particular for our large regions (in `memory.c`).
-    // However, some systems only allow THP if called with explicit `madvise`, so
-    // when large OS pages are enabled for mimalloc, we call `madvice` anyways.
-    if (allow_large && use_large_os_page(size, try_alignment)) {
-      if (madvise(p, size, MADV_HUGEPAGE) == 0) {
-        *is_large = true; // possibly
-      };
-    }
-    #endif
-    #if defined(__sun)
-    if (allow_large && use_large_os_page(size, try_alignment)) {
-      struct memcntl_mha cmd = {0};
-      cmd.mha_pagesize = large_os_page_size;
-      cmd.mha_cmd = MHA_MAPSIZE_VA;
-      if (memcntl(p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) {
-        *is_large = true;
+    if (p != NULL) {
+      #if defined(MADV_HUGEPAGE)
+      // Many Linux systems don't allow MAP_HUGETLB but they support instead
+      // transparent huge pages (THP). Generally, it is not required to call `madvise` with MADV_HUGE
+      // though since properly aligned allocations will already use large pages if available
+      // in that case -- in particular for our large regions (in `memory.c`).
+      // However, some systems only allow THP if called with explicit `madvise`, so
+      // when large OS pages are enabled for mimalloc, we call `madvise` anyways.
+      if (allow_large && use_large_os_page(size, try_alignment)) {
+        if (mi_madvise(p, size, MADV_HUGEPAGE) == 0) {
+          *is_large = true; // possibly
+        };
       }
+      #elif defined(__sun)
+      if (allow_large && use_large_os_page(size, try_alignment)) {
+        struct memcntl_mha cmd = {0};
+        cmd.mha_pagesize = large_os_page_size;
+        cmd.mha_cmd = MHA_MAPSIZE_VA;
+        if (memcntl((caddr_t)p, size, MC_HAT_ADVISE, (caddr_t)&cmd, 0, 0) == 0) {
+          *is_large = true;
+        }
+      }      
+      #endif
     }
-    #endif
   }
   if (p == NULL) {
     _mi_warning_message("unable to allocate OS memory (%zu bytes, error code: %i, address: %p, large only: %d, allow large: %d)\n", size, errno, addr, large_only, allow_large);
@@ -457,42 +696,17 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
 }
 #endif
 
-// On 64-bit systems, we can do efficient aligned allocation by using
-// the 4TiB to 30TiB area to allocate them.
-#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || (defined(MI_OS_USE_MMAP) && !defined(MAP_ALIGNED)))
-static volatile mi_decl_cache_align _Atomic(uintptr_t) aligned_base;
-
-// Return a 4MiB aligned address that is probably available
-static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
-  if (try_alignment == 0 || try_alignment > MI_SEGMENT_SIZE) return NULL;
-  if ((size%MI_SEGMENT_SIZE) != 0) return NULL;
-  uintptr_t hint = mi_atomic_add(&aligned_base, size);
-  if (hint == 0 || hint > ((intptr_t)30<<40)) { // try to wrap around after 30TiB (area after 32TiB is used for huge OS pages)
-    uintptr_t init = ((uintptr_t)4 << 40); // start at 4TiB area
-    #if (MI_SECURE>0 || MI_DEBUG==0)     // security: randomize start of aligned allocations unless in debug mode
-    uintptr_t r = _mi_heap_random_next(mi_get_default_heap());
-    init = init + (MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF));  // (randomly 20 bits)*4MiB == 0 to 4TiB
-    #endif
-    mi_atomic_cas_strong(&aligned_base, init, hint + size);
-    hint = mi_atomic_add(&aligned_base, size); // this may still give 0 or > 30TiB but that is ok, it is a hint after all
-  }
-  if (hint%try_alignment != 0) return NULL;
-  return (void*)hint;
-}
-#else
-static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
-  UNUSED(try_alignment); UNUSED(size);
-  return NULL;
-}
-#endif
 
+/* -----------------------------------------------------------
+   Primitive allocation from the OS.
+-------------------------------------------------------------- */
 
-// Primitive allocation from the OS.
 // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
 static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) {
   mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
   if (size == 0) return NULL;
   if (!commit) allow_large = false;
+  if (try_alignment == 0) try_alignment = 1; // avoid 0 to ensure there will be no divide by zero when aligning
 
   void* p = NULL;
   /*
@@ -507,11 +721,12 @@ static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, boo
 
   #if defined(_WIN32)
     int flags = MEM_RESERVE;
-    if (commit) flags |= MEM_COMMIT;
+    if (commit) { flags |= MEM_COMMIT; }
     p = mi_win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large);
-  #elif defined(__wasi__)
+  #elif defined(MI_USE_SBRK) || defined(__wasi__)
+    MI_UNUSED(allow_large);
     *is_large = false;
-    p = mi_wasm_heap_grow(size, try_alignment);
+    p = mi_heap_grow(size, try_alignment);
   #else
     int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
     p = mi_unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large);
@@ -530,6 +745,7 @@ static void* mi_os_mem_alloc(size_t size, size_t try_alignment, bool commit, boo
 static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) {
   mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
   mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
+  mi_assert_internal(is_large != NULL);
   if (!commit) allow_large = false;
   if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
   size = _mi_align_up(size, _mi_os_page_size());
@@ -537,47 +753,33 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
   // try first with a hint (this will be aligned directly on Win 10+ or BSD)
   void* p = mi_os_mem_alloc(size, alignment, commit, allow_large, is_large, stats);
   if (p == NULL) return NULL;
-
+  
   // if not aligned, free it, overallocate, and unmap around it
   if (((uintptr_t)p % alignment != 0)) {
     mi_os_mem_free(p, size, commit, stats);
+    _mi_warning_message("unable to allocate aligned OS memory directly, fall back to over-allocation (%zu bytes, address: %p, alignment: %zu, commit: %d)\n", size, p, alignment, commit);
     if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
-    size_t over_size = size + alignment;
+    const size_t over_size = size + alignment;
 
 #if _WIN32
-    // over-allocate and than re-allocate exactly at an aligned address in there.
-    // this may fail due to threads allocating at the same time so we
-    // retry this at most 3 times before giving up.
-    // (we can not decommit around the overallocation on Windows, because we can only
-    //  free the original pointer, not one pointing inside the area)
-    int flags = MEM_RESERVE;
-    if (commit) flags |= MEM_COMMIT;
-    for (int tries = 0; tries < 3; tries++) {
-      // over-allocate to determine a virtual memory range
-      p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats);
-      if (p == NULL) return NULL; // error
-      if (((uintptr_t)p % alignment) == 0) {
-        // if p happens to be aligned, just decommit the left-over area
-        _mi_os_decommit((uint8_t*)p + size, over_size - size, stats);
-        break;
-      }
-      else {
-        // otherwise free and allocate at an aligned address in there
-        mi_os_mem_free(p, over_size, commit, stats);
-        void* aligned_p = mi_align_up_ptr(p, alignment);
-        p = mi_win_virtual_alloc(aligned_p, size, alignment, flags, false, allow_large, is_large);
-        if (p == aligned_p) break; // success!
-        if (p != NULL) { // should not happen?
-          mi_os_mem_free(p, size, commit, stats);
-          p = NULL;
-        }
-      }
+    // over-allocate uncommitted (virtual) memory
+    p = mi_os_mem_alloc(over_size, 0 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, stats);
+    if (p == NULL) return NULL;
+    
+    // set p to the aligned part in the full region
+    // note: this is dangerous on Windows as VirtualFree needs the actual region pointer
+    // but in mi_os_mem_free we handle this (hopefully exceptional) situation.
+    p = mi_align_up_ptr(p, alignment);
+
+    // explicitly commit only the aligned part
+    if (commit) {
+      _mi_os_commit(p, size, NULL, stats);
     }
 #else
     // overallocate...
-    p = mi_os_mem_alloc(over_size, alignment, commit, false, is_large, stats);
+    p = mi_os_mem_alloc(over_size, 1, commit, false, is_large, stats);
     if (p == NULL) return NULL;
-    // and selectively unmap parts around the over-allocated area.
+    // and selectively unmap parts around the over-allocated area. (noop on sbrk)
     void* aligned_p = mi_align_up_ptr(p, alignment);
     size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
     size_t mid_size = _mi_align_up(size, _mi_os_page_size());
@@ -585,7 +787,7 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
     mi_assert_internal(pre_size < over_size && post_size < over_size && mid_size >= size);
     if (pre_size > 0)  mi_os_mem_free(p, pre_size, commit, stats);
     if (post_size > 0) mi_os_mem_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats);
-    // we can return the aligned pointer on `mmap` systems
+    // we can return the aligned pointer on `mmap` (and sbrk) systems
     p = aligned_p;
 #endif
   }
@@ -594,18 +796,23 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
   return p;
 }
 
+
 /* -----------------------------------------------------------
   OS API: alloc, free, alloc_aligned
 ----------------------------------------------------------- */
 
-void* _mi_os_alloc(size_t size, mi_stats_t* stats) {
+void* _mi_os_alloc(size_t size, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
   if (size == 0) return NULL;
   size = _mi_os_good_alloc_size(size);
   bool is_large = false;
   return mi_os_mem_alloc(size, 0, true, false, &is_large, stats);
 }
 
-void  _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats) {
+void  _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
   if (size == 0 || p == NULL) return;
   size = _mi_os_good_alloc_size(size);
   mi_os_mem_free(p, size, was_committed, stats);
@@ -615,8 +822,10 @@ void  _mi_os_free(void* p, size_t size, mi_stats_t* stats) {
   _mi_os_free_ex(p, size, true, stats);
 }
 
-void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld)
+void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_stats_t* tld_stats)
 {
+  MI_UNUSED(&mi_os_get_aligned_hint); // suppress unused warnings
+  MI_UNUSED(tld_stats);
   if (size == 0) return NULL;
   size = _mi_os_good_alloc_size(size);
   alignment = _mi_align_up(alignment, _mi_os_page_size());
@@ -625,7 +834,7 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* lar
     allow_large = *large;
     *large = false;
   }
-  return mi_os_mem_alloc_aligned(size, alignment, commit, allow_large, (large!=NULL?large:&allow_large), tld->stats);
+  return mi_os_mem_alloc_aligned(size, alignment, commit, allow_large, (large!=NULL?large:&allow_large), &_mi_stats_main /*tld->stats*/ );
 }
 
 
@@ -667,7 +876,7 @@ static void mi_mprotect_hint(int err) {
                         "  > sudo sysctl -w vm.max_map_count=262144\n");
   }
 #else
-  UNUSED(err);
+  MI_UNUSED(err);
 #endif
 }
 
@@ -682,17 +891,16 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
   if (csize == 0) return true;  // || _mi_os_is_huge_reserved(addr))
   int err = 0;
   if (commit) {
-    _mi_stat_increase(&stats->committed, csize);
+    _mi_stat_increase(&stats->committed, size);  // use size for precise commit vs. decommit
     _mi_stat_counter_increase(&stats->commit_calls, 1);
   }
   else {
-    _mi_stat_decrease(&stats->committed, csize);
+    _mi_stat_decrease(&stats->committed, size);
   }
 
   #if defined(_WIN32)
   if (commit) {
-    // if the memory was already committed, the call succeeds but it is not zero'd
-    // *is_zero = true;
+    // *is_zero = true;  // note: if the memory was already committed, the call succeeds but the memory is not zero'd
     void* p = VirtualAlloc(start, csize, MEM_COMMIT, PAGE_READWRITE);
     err = (p == start ? 0 : GetLastError());
   }
@@ -702,41 +910,68 @@ static bool mi_os_commitx(void* addr, size_t size, bool commit, bool conservativ
   }
   #elif defined(__wasi__)
   // WebAssembly guests can't control memory protection
-  #elif defined(MAP_FIXED)
-  if (!commit) {
-    // use mmap with MAP_FIXED to discard the existing memory (and reduce commit charge)
-    void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), -1, 0);
+  #elif 0 && defined(MAP_FIXED) && !defined(__APPLE__)
+  // Linux: disabled for now as mmap fixed seems much more expensive than MADV_DONTNEED (and splits VMA's?)
+  if (commit) {
+    // commit: just change the protection
+    err = mprotect(start, csize, (PROT_READ | PROT_WRITE));
+    if (err != 0) { err = errno; }
+  } 
+  else {
+    // decommit: use mmap with MAP_FIXED to discard the existing memory (and reduce rss)
+    const int fd = mi_unix_mmap_fd();
+    void* p = mmap(start, csize, PROT_NONE, (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE), fd, 0);
     if (p != start) { err = errno; }
   }
-  else {
-    // for commit, just change the protection
+  #else
+  // Linux, macOSX and others.
+  if (commit) {
+    // commit: ensure we can access the area    
     err = mprotect(start, csize, (PROT_READ | PROT_WRITE));
     if (err != 0) { err = errno; }
+  } 
+  else {
+    #if defined(MADV_DONTNEED) && MI_DEBUG == 0 && MI_SECURE == 0
+    // decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
+    // (on the other hand, MADV_FREE would be good enough.. it is just not reflected in the stats :-( )
+    err = madvise(start, csize, MADV_DONTNEED);
+    #else
+    // decommit: just disable access (also used in debug and secure mode to trap on illegal access)
+    err = mprotect(start, csize, PROT_NONE);
+    if (err != 0) { err = errno; }
+    #endif
+    //#if defined(MADV_FREE_REUSE)
+    //  while ((err = mi_madvise(start, csize, MADV_FREE_REUSE)) != 0 && errno == EAGAIN) { errno = 0; }
+    //#endif
   }
-  #else
-  err = mprotect(start, csize, (commit ? (PROT_READ | PROT_WRITE) : PROT_NONE));
-  if (err != 0) { err = errno; }
   #endif
   if (err != 0) {
-    _mi_warning_message("%s error: start: %p, csize: 0x%x, err: %i\n", commit ? "commit" : "decommit", start, csize, err);
+    _mi_warning_message("%s error: start: %p, csize: 0x%zx, err: %i\n", commit ? "commit" : "decommit", start, csize, err);
     mi_mprotect_hint(err);
   }
   mi_assert_internal(err == 0);
   return (err == 0);
 }
 
-bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
+bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
   return mi_os_commitx(addr, size, true, false /* liberal */, is_zero, stats);
 }
 
-bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats) {
+bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
   bool is_zero;
   return mi_os_commitx(addr, size, false, true /* conservative */, &is_zero, stats);
 }
 
-bool _mi_os_commit_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
-  return mi_os_commitx(addr, size, true, true /* conservative */, is_zero, stats);
+/*
+static bool mi_os_commit_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {  
+  return mi_os_commitx(addr, size, true, true // conservative
+                      , is_zero, stats);
 }
+*/
 
 // Signal to the OS that the address range is no longer in use
 // but may be used later again. This will release physical memory
@@ -769,20 +1004,22 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
   if (p != start) return false;
 #else
 #if defined(MADV_FREE)
-  static int advice = MADV_FREE;
-  int err = madvise(start, csize, advice);
-  if (err != 0 && errno == EINVAL && advice == MADV_FREE) {
+  static _Atomic(size_t) advice = MI_ATOMIC_VAR_INIT(MADV_FREE);
+  int oadvice = (int)mi_atomic_load_relaxed(&advice);
+  int err;
+  while ((err = mi_madvise(start, csize, oadvice)) != 0 && errno == EAGAIN) { errno = 0;  };
+  if (err != 0 && errno == EINVAL && oadvice == MADV_FREE) {  
     // if MADV_FREE is not supported, fall back to MADV_DONTNEED from now on
-    advice = MADV_DONTNEED;
-    err = madvise(start, csize, advice);
+    mi_atomic_store_release(&advice, (size_t)MADV_DONTNEED);
+    err = mi_madvise(start, csize, MADV_DONTNEED);
   }
 #elif defined(__wasi__)
   int err = 0;
 #else
-  int err = madvise(start, csize, MADV_DONTNEED);
+  int err = mi_madvise(start, csize, MADV_DONTNEED);
 #endif
   if (err != 0) {
-    _mi_warning_message("madvise reset error: start: %p, csize: 0x%x, errno: %i\n", start, csize, errno);
+    _mi_warning_message("madvise reset error: start: %p, csize: 0x%zx, errno: %i\n", start, csize, errno);
   }
   //mi_assert(err == 0);
   if (err != 0) return false;
@@ -794,25 +1031,25 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats)
 // but may be used later again. This will release physical memory
 // pages and reduce swapping while keeping the memory committed.
 // We page align to a conservative area inside the range to reset.
-bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) {
-  if (mi_option_is_enabled(mi_option_reset_decommits)) {
-    return _mi_os_decommit(addr, size, stats);
-  }
-  else {
-    return mi_os_resetx(addr, size, true, stats);
-  }
+bool _mi_os_reset(void* addr, size_t size, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
+  return mi_os_resetx(addr, size, true, stats);
 }
 
-bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* stats) {
+/*
+bool _mi_os_unreset(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
+  MI_UNUSED(tld_stats);
+  mi_stats_t* stats = &_mi_stats_main;
   if (mi_option_is_enabled(mi_option_reset_decommits)) {
-    return _mi_os_commit_unreset(addr, size, is_zero, stats);  // re-commit it (conservatively!)
+    return mi_os_commit_unreset(addr, size, is_zero, stats);  // re-commit it (conservatively!)
   }
   else {
     *is_zero = false;
     return mi_os_resetx(addr, size, false, stats);
   }
 }
-
+*/
 
 // Protect a region in memory to be not accessible.
 static  bool mi_os_protectx(void* addr, size_t size, bool protect) {
@@ -837,7 +1074,7 @@ static  bool mi_os_protectx(void* addr, size_t size, bool protect) {
   if (err != 0) { err = errno; }
 #endif
   if (err != 0) {
-    _mi_warning_message("mprotect error: start: %p, csize: 0x%x, err: %i\n", start, csize, err);
+    _mi_warning_message("mprotect error: start: %p, csize: 0x%zx, err: %i\n", start, csize, err);
     mi_mprotect_hint(err);
   }
   return (err == 0);
@@ -878,32 +1115,28 @@ bool _mi_os_shrink(void* p, size_t oldsize, size_t newsize, mi_stats_t* stats) {
 Support for allocating huge OS pages (1Gib) that are reserved up-front
 and possibly associated with a specific NUMA node. (use `numa_node>=0`)
 -----------------------------------------------------------------------------*/
-#define MI_HUGE_OS_PAGE_SIZE  (GiB)
+#define MI_HUGE_OS_PAGE_SIZE  (MI_GiB)
 
 #if defined(_WIN32) && (MI_INTPTR_SIZE >= 8)
 static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node)
 {
-  mi_assert_internal(size%GiB == 0);
+  mi_assert_internal(size%MI_GiB == 0);
   mi_assert_internal(addr != NULL);
   const DWORD flags = MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE;
 
   mi_win_enable_large_os_pages();
 
-  #if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
-  MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} };
+  MI_MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} };
   // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages
   static bool mi_huge_pages_available = true;
   if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) {
-    #ifndef MEM_EXTENDED_PARAMETER_NONPAGED_HUGE
-    #define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE  (0x10)
-    #endif
-    params[0].Type = 5; // == MemExtendedParameterAttributeFlags;
-    params[0].ULong64 = MEM_EXTENDED_PARAMETER_NONPAGED_HUGE;
+    params[0].Type.Type = MiMemExtendedParameterAttributeFlags;
+    params[0].Arg.ULong64 = MI_MEM_EXTENDED_PARAMETER_NONPAGED_HUGE;
     ULONG param_count = 1;
     if (numa_node >= 0) {
       param_count++;
-      params[1].Type = MemExtendedParameterNumaNode;
-      params[1].ULong = (unsigned)numa_node;
+      params[1].Type.Type = MiMemExtendedParameterNumaNode;
+      params[1].Arg.ULong = (unsigned)numa_node;
     }
     SIZE_T psize = size;
     void* base = addr;
@@ -914,18 +1147,16 @@ static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node)
     else {
       // fall back to regular large pages
       mi_huge_pages_available = false; // don't try further huge pages
-      _mi_warning_message("unable to allocate using huge (1gb) pages, trying large (2mb) pages instead (status 0x%lx)\n", err);
+      _mi_warning_message("unable to allocate using huge (1GiB) pages, trying large (2MiB) pages instead (status 0x%lx)\n", err);
     }
   }
   // on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation
   if (pVirtualAlloc2 != NULL && numa_node >= 0) {
-    params[0].Type = MemExtendedParameterNumaNode;
-    params[0].ULong = (unsigned)numa_node;
+    params[0].Type.Type = MiMemExtendedParameterNumaNode;
+    params[0].Arg.ULong = (unsigned)numa_node;
     return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, params, 1);
   }
-  #else
-    UNUSED(numa_node);
-  #endif
+  
   // otherwise use regular virtual alloc on older windows
   return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
 }
@@ -941,30 +1172,30 @@ static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, cons
 }
 #else
 static long mi_os_mbind(void* start, unsigned long len, unsigned long mode, const unsigned long* nmask, unsigned long maxnode, unsigned flags) {
-  UNUSED(start); UNUSED(len); UNUSED(mode); UNUSED(nmask); UNUSED(maxnode); UNUSED(flags);
+  MI_UNUSED(start); MI_UNUSED(len); MI_UNUSED(mode); MI_UNUSED(nmask); MI_UNUSED(maxnode); MI_UNUSED(flags);
   return 0;
 }
 #endif
 static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) {
-  mi_assert_internal(size%GiB == 0);
+  mi_assert_internal(size%MI_GiB == 0);
   bool is_large = true;
   void* p = mi_unix_mmap(addr, size, MI_SEGMENT_SIZE, PROT_READ | PROT_WRITE, true, true, &is_large);
   if (p == NULL) return NULL;
   if (numa_node >= 0 && numa_node < 8*MI_INTPTR_SIZE) { // at most 64 nodes
-    uintptr_t numa_mask = (1UL << numa_node);
+    unsigned long numa_mask = (1UL << numa_node);
     // TODO: does `mbind` work correctly for huge OS pages? should we
     // use `set_mempolicy` before calling mmap instead?
     // see: <https://lkml.org/lkml/2017/2/9/875>
     long err = mi_os_mbind(p, size, MPOL_PREFERRED, &numa_mask, 8*MI_INTPTR_SIZE, 0);
     if (err != 0) {
-      _mi_warning_message("failed to bind huge (1gb) pages to numa node %d: %s\n", numa_node, strerror(errno));
+      _mi_warning_message("failed to bind huge (1GiB) pages to numa node %d: %s\n", numa_node, strerror(errno));
     }
   }
   return p;
 }
 #else
 static void* mi_os_alloc_huge_os_pagesx(void* addr, size_t size, int numa_node) {
-  UNUSED(addr); UNUSED(size); UNUSED(numa_node);
+  MI_UNUSED(addr); MI_UNUSED(size); MI_UNUSED(numa_node);
   return NULL;
 }
 #endif
@@ -980,9 +1211,9 @@ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
 
   uintptr_t start = 0;
   uintptr_t end = 0;
-  uintptr_t expected;
+  uintptr_t huge_start = mi_atomic_load_relaxed(&mi_huge_start);
   do {
-    start = expected = mi_atomic_read_relaxed(&mi_huge_start);
+    start = huge_start;
     if (start == 0) {
       // Initialize the start address after the 32TiB area
       start = ((uintptr_t)32 << 40);  // 32TiB virtual start address
@@ -993,14 +1224,14 @@ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
     }
     end = start + size;
     mi_assert_internal(end % MI_SEGMENT_SIZE == 0);
-  } while (!mi_atomic_cas_strong(&mi_huge_start, end, expected));
+  } while (!mi_atomic_cas_strong_acq_rel(&mi_huge_start, &huge_start, end));
 
   if (total_size != NULL) *total_size = size;
   return (uint8_t*)start;
 }
 #else
 static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
-  UNUSED(pages);
+  MI_UNUSED(pages);
   if (total_size != NULL) *total_size = 0;
   return NULL;
 }
@@ -1054,8 +1285,8 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse
     }
   }
   mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size);
-  if (pages_reserved != NULL) *pages_reserved = page;
-  if (psize != NULL) *psize = page * MI_HUGE_OS_PAGE_SIZE;
+  if (pages_reserved != NULL) { *pages_reserved = page; }
+  if (psize != NULL) { *psize = page * MI_HUGE_OS_PAGE_SIZE; }
   return (page == 0 ? NULL : start);
 }
 
@@ -1067,6 +1298,7 @@ void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats) {
   while (size >= MI_HUGE_OS_PAGE_SIZE) {
     _mi_os_free(base, MI_HUGE_OS_PAGE_SIZE, stats);
     size -= MI_HUGE_OS_PAGE_SIZE;
+    base += MI_HUGE_OS_PAGE_SIZE;
   }
 }
 
@@ -1074,11 +1306,11 @@ void _mi_os_free_huge_pages(void* p, size_t size, mi_stats_t* stats) {
 Support NUMA aware allocation
 -----------------------------------------------------------------------------*/
 #ifdef _WIN32  
-static size_t mi_os_numa_nodex() {
+static size_t mi_os_numa_nodex(void) {
   USHORT numa_node = 0;
   if (pGetCurrentProcessorNumberEx != NULL && pGetNumaProcessorNodeEx != NULL) {
     // Extended API is supported
-    PROCESSOR_NUMBER pnum;
+    MI_PROCESSOR_NUMBER pnum;
     (*pGetCurrentProcessorNumberEx)(&pnum);
     USHORT nnode = 0;
     BOOL ok = (*pGetNumaProcessorNodeEx)(&pnum, &nnode);
@@ -1143,6 +1375,35 @@ static size_t mi_os_numa_node_countx(void) {
   }
   return (node+1);
 }
+#elif defined(__FreeBSD__) && __FreeBSD_version >= 1200000
+static size_t mi_os_numa_nodex(void) {
+  domainset_t dom;
+  size_t node;
+  int policy;
+  if (cpuset_getdomain(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, sizeof(dom), &dom, &policy) == -1) return 0ul;
+  for (node = 0; node < MAXMEMDOM; node++) {
+    if (DOMAINSET_ISSET(node, &dom)) return node;
+  }
+  return 0ul;
+}
+static size_t mi_os_numa_node_countx(void) {
+  size_t ndomains = 0;
+  size_t len = sizeof(ndomains);
+  if (sysctlbyname("vm.ndomains", &ndomains, &len, NULL, 0) == -1) return 0ul;
+  return ndomains;
+}
+#elif defined(__DragonFly__)
+static size_t mi_os_numa_nodex(void) {
+  // TODO: DragonFly does not seem to provide any userland means to get this information.
+  return 0ul;
+}
+static size_t mi_os_numa_node_countx(void) {
+  size_t ncpus = 0, nvirtcoresperphys = 0;
+  size_t len = sizeof(size_t);
+  if (sysctlbyname("hw.ncpu", &ncpus, &len, NULL, 0) == -1) return 0ul;
+  if (sysctlbyname("hw.cpu_topology_ht_ids", &nvirtcoresperphys, &len, NULL, 0) == -1) return 0ul;
+  return nvirtcoresperphys * ncpus;
+}
 #else
 static size_t mi_os_numa_nodex(void) {
   return 0;
@@ -1152,21 +1413,27 @@ static size_t mi_os_numa_node_countx(void) {
 }
 #endif
 
-size_t _mi_numa_node_count = 0;   // cache the node count
+_Atomic(size_t)  _mi_numa_node_count; // = 0   // cache the node count
 
 size_t _mi_os_numa_node_count_get(void) {
-  if (mi_unlikely(_mi_numa_node_count <= 0)) {
+  size_t count = mi_atomic_load_acquire(&_mi_numa_node_count);
+  if (count <= 0) {
     long ncount = mi_option_get(mi_option_use_numa_nodes); // given explicitly?
-    if (ncount <= 0) ncount = (long)mi_os_numa_node_countx();        // or detect dynamically
-    _mi_numa_node_count = (size_t)(ncount <= 0 ? 1 : ncount);
-    _mi_verbose_message("using %zd numa regions\n", _mi_numa_node_count);
+    if (ncount > 0) {
+      count = (size_t)ncount;
+    }
+    else {
+      count = mi_os_numa_node_countx(); // or detect dynamically
+      if (count == 0) count = 1;
+    }    
+    mi_atomic_store_release(&_mi_numa_node_count, count); // save it
+    _mi_verbose_message("using %zd numa regions\n", count);
   }
-  mi_assert_internal(_mi_numa_node_count >= 1);
-  return _mi_numa_node_count;
+  return count;
 }
 
 int _mi_os_numa_node_get(mi_os_tld_t* tld) {
-  UNUSED(tld);
+  MI_UNUSED(tld);
   size_t numa_count = _mi_os_numa_node_count();
   if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0
   // never more than the node count and >= 0
index ea2130192b145c5ecd76c99a19866b606de7884c..92f933c2a0d798eac4285213f6abc86fac004438 100644 (file)
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -34,70 +34,26 @@ terms of the MIT license. A copy of the license can be found in the file
 
 
 static inline bool mi_page_queue_is_huge(const mi_page_queue_t* pq) {
-  return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+sizeof(uintptr_t)));
+  return (pq->block_size == (MI_MEDIUM_OBJ_SIZE_MAX+sizeof(uintptr_t)));
 }
 
 static inline bool mi_page_queue_is_full(const mi_page_queue_t* pq) {
-  return (pq->block_size == (MI_LARGE_OBJ_SIZE_MAX+(2*sizeof(uintptr_t))));
+  return (pq->block_size == (MI_MEDIUM_OBJ_SIZE_MAX+(2*sizeof(uintptr_t))));
 }
 
 static inline bool mi_page_queue_is_special(const mi_page_queue_t* pq) {
-  return (pq->block_size > MI_LARGE_OBJ_SIZE_MAX);
+  return (pq->block_size > MI_MEDIUM_OBJ_SIZE_MAX);
 }
 
 /* -----------------------------------------------------------
   Bins
 ----------------------------------------------------------- */
 
-// Bit scan reverse: return the index of the highest bit.
-static inline uint8_t mi_bsr32(uint32_t x);
-
-#if defined(_MSC_VER)
-#include <intrin.h>
-static inline uint8_t mi_bsr32(uint32_t x) {
-  uint32_t idx;
-  _BitScanReverse((DWORD*)&idx, x);
-  return (uint8_t)idx;
-}
-#elif defined(__GNUC__) || defined(__clang__)
-static inline uint8_t mi_bsr32(uint32_t x) {
-  return (31 - __builtin_clz(x));
-}
-#else
-static inline uint8_t mi_bsr32(uint32_t x) {
-  // de Bruijn multiplication, see <http://supertech.csail.mit.edu/papers/debruijn.pdf>
-  static const uint8_t debruijn[32] = {
-     31,  0, 22,  1, 28, 23, 18,  2, 29, 26, 24, 10, 19,  7,  3, 12,
-     30, 21, 27, 17, 25,  9,  6, 11, 20, 16,  8,  5, 15,  4, 14, 13,
-  };
-  x |= x >> 1;
-  x |= x >> 2;
-  x |= x >> 4;
-  x |= x >> 8;
-  x |= x >> 16;
-  x++;
-  return debruijn[(x*0x076be629) >> 27];
-}
-#endif
-
-// Bit scan reverse: return the index of the highest bit.
-uint8_t _mi_bsr(uintptr_t x) {
-  if (x == 0) return 0;
-#if MI_INTPTR_SIZE==8
-  uint32_t hi = (x >> 32);
-  return (hi == 0 ? mi_bsr32((uint32_t)x) : 32 + mi_bsr32(hi));
-#elif MI_INTPTR_SIZE==4
-  return mi_bsr32(x);
-#else
-# error "define bsr for non-32 or 64-bit platforms"
-#endif
-}
-
 // Return the bin for a given field size.
 // Returns MI_BIN_HUGE if the size is too large.
 // We use `wsize` for the size in "machine word sizes",
 // i.e. byte size == `wsize*sizeof(void*)`.
-extern inline uint8_t _mi_bin(size_t size) {
+static inline uint8_t mi_bin(size_t size) {
   size_t wsize = _mi_wsize_from_size(size);
   uint8_t bin;
   if (wsize <= 1) {
@@ -116,16 +72,16 @@ extern inline uint8_t _mi_bin(size_t size) {
     bin = (uint8_t)wsize;
   }
   #endif
-  else if (wsize > MI_LARGE_OBJ_WSIZE_MAX) {
+  else if (wsize > MI_MEDIUM_OBJ_WSIZE_MAX) {
     bin = MI_BIN_HUGE;
   }
   else {
-    #if defined(MI_ALIGN4W) 
+    #if defined(MI_ALIGN4W)
     if (wsize <= 16) { wsize = (wsize+3)&~3; } // round to 4x word sizes
     #endif
     wsize--;
     // find the highest bit
-    uint8_t b = mi_bsr32((uint32_t)wsize);
+    uint8_t b = (uint8_t)mi_bsr(wsize);  // note: wsize != 0
     // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation).
     // - adjust with 3 because we use do not round the first 8 sizes
     //   which each get an exact bin
@@ -142,14 +98,18 @@ extern inline uint8_t _mi_bin(size_t size) {
   Queue of pages with free blocks
 ----------------------------------------------------------- */
 
+uint8_t _mi_bin(size_t size) {
+  return mi_bin(size);
+}
+
 size_t _mi_bin_size(uint8_t bin) {
   return _mi_heap_empty.pages[bin].block_size;
 }
 
 // Good size for allocation
 size_t mi_good_size(size_t size) mi_attr_noexcept {
-  if (size <= MI_LARGE_OBJ_SIZE_MAX) {
-    return _mi_bin_size(_mi_bin(size));
+  if (size <= MI_MEDIUM_OBJ_SIZE_MAX) {
+    return _mi_bin_size(mi_bin(size));
   }
   else {
     return _mi_align_up(size,_mi_os_page_size());
@@ -178,7 +138,7 @@ static bool mi_heap_contains_queue(const mi_heap_t* heap, const mi_page_queue_t*
 #endif
 
 static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) {
-  uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size));
+  uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : mi_bin(page->xblock_size));
   mi_heap_t* heap = mi_page_heap(page);
   mi_assert_internal(heap != NULL && bin <= MI_BIN_FULL);
   mi_page_queue_t* pq = &heap->pages[bin];
@@ -188,7 +148,7 @@ static mi_page_queue_t* mi_page_queue_of(const mi_page_t* page) {
 }
 
 static mi_page_queue_t* mi_heap_page_queue_of(mi_heap_t* heap, const mi_page_t* page) {
-  uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : _mi_bin(page->xblock_size));
+  uint8_t bin = (mi_page_is_in_full(page) ? MI_BIN_FULL : mi_bin(page->xblock_size));
   mi_assert_internal(bin <= MI_BIN_FULL);
   mi_page_queue_t* pq = &heap->pages[bin];
   mi_assert_internal(mi_page_is_in_full(page) || page->xblock_size == pq->block_size);
@@ -221,9 +181,9 @@ static inline void mi_heap_queue_first_update(mi_heap_t* heap, const mi_page_que
   }
   else {
     // find previous size; due to minimal alignment upto 3 previous bins may need to be skipped
-    uint8_t bin = _mi_bin(size);
+    uint8_t bin = mi_bin(size);
     const mi_page_queue_t* prev = pq - 1;
-    while( bin == _mi_bin(prev->block_size) && prev > &heap->pages[0]) {
+    while( bin == mi_bin(prev->block_size) && prev > &heap->pages[0]) {
       prev--;
     }
     start = 1 + _mi_wsize_from_size(prev->block_size);
@@ -246,8 +206,9 @@ static bool mi_page_queue_is_empty(mi_page_queue_t* queue) {
 static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) {
   mi_assert_internal(page != NULL);
   mi_assert_expensive(mi_page_queue_contains(queue, page));
-  mi_assert_internal(page->xblock_size == queue->block_size || (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue))  || (mi_page_is_in_full(page) && mi_page_queue_is_full(queue)));
+  mi_assert_internal(page->xblock_size == queue->block_size || (page->xblock_size > MI_MEDIUM_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue))  || (mi_page_is_in_full(page) && mi_page_queue_is_full(queue)));
   mi_heap_t* heap = mi_page_heap(page);
+
   if (page->prev != NULL) page->prev->next = page->next;
   if (page->next != NULL) page->next->prev = page->prev;
   if (page == queue->last)  queue->last = page->prev;
@@ -260,7 +221,7 @@ static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) {
   heap->page_count--;
   page->next = NULL;
   page->prev = NULL;
-  // mi_atomic_write_ptr(mi_atomic_cast(void*, &page->heap), NULL);
+  // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), NULL);
   mi_page_set_in_full(page,false);
 }
 
@@ -268,13 +229,14 @@ static void mi_page_queue_remove(mi_page_queue_t* queue, mi_page_t* page) {
 static void mi_page_queue_push(mi_heap_t* heap, mi_page_queue_t* queue, mi_page_t* page) {
   mi_assert_internal(mi_page_heap(page) == heap);
   mi_assert_internal(!mi_page_queue_contains(queue, page));
-  mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE);
+
+  mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE);
   mi_assert_internal(page->xblock_size == queue->block_size ||
-                      (page->xblock_size > MI_LARGE_OBJ_SIZE_MAX && mi_page_queue_is_huge(queue)) ||
+                      (page->xblock_size > MI_MEDIUM_OBJ_SIZE_MAX) ||
                         (mi_page_is_in_full(page) && mi_page_queue_is_full(queue)));
 
   mi_page_set_in_full(page, mi_page_queue_is_full(queue));
-  // mi_atomic_write_ptr(mi_atomic_cast(void*, &page->heap), heap);
+  // mi_atomic_store_ptr_release(mi_atomic_cast(void*, &page->heap), heap);
   page->next = queue->first;
   page->prev = NULL;
   if (queue->first != NULL) {
@@ -296,6 +258,7 @@ static void mi_page_queue_enqueue_from(mi_page_queue_t* to, mi_page_queue_t* fro
   mi_assert_internal(page != NULL);
   mi_assert_expensive(mi_page_queue_contains(from, page));
   mi_assert_expensive(!mi_page_queue_contains(to, page));
+
   mi_assert_internal((page->xblock_size == to->block_size && page->xblock_size == from->block_size) ||
                      (page->xblock_size == to->block_size && mi_page_queue_is_full(from)) ||
                      (page->xblock_size == from->block_size && mi_page_queue_is_full(to)) ||
@@ -341,7 +304,7 @@ size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue
   for (mi_page_t* page = append->first; page != NULL; page = page->next) {
     // inline `mi_page_set_heap` to avoid wrong assertion during absorption;
     // in this case it is ok to be delayed freeing since both "to" and "from" heap are still alive.
-    mi_atomic_write(&page->xheap, (uintptr_t)heap); 
+    mi_atomic_store_release(&page->xheap, (uintptr_t)heap); 
     // set the flag to delayed free (not overriding NEVER_DELAYED_FREE) which has as a
     // side effect that it spins until any DELAYED_FREEING is finished. This ensures
     // that after appending only the new heap will be used for delayed free operations.
index c8a4e54b0bdb8c95aa16a4d243f2a89fd20a37a0..fd6c5397d021bd1daee4cf129f5356877d16b789 100644 (file)
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -7,7 +7,7 @@ terms of the MIT license. A copy of the license can be found in the file
 
 /* -----------------------------------------------------------
   The core of the allocator. Every segment contains
-  pages of a {certain block size. The main function
+  pages of a certain block size. The main function
   exported is `mi_malloc_generic`.
 ----------------------------------------------------------- */
 
@@ -30,7 +30,7 @@ terms of the MIT license. A copy of the license can be found in the file
 
 // Index a block in a page
 static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_start, size_t block_size, size_t i) {
-  UNUSED(page);
+  MI_UNUSED(page);
   mi_assert_internal(page != NULL);
   mi_assert_internal(i <= page->reserved);
   return (mi_block_t*)((uint8_t*)page_start + (i * block_size));
@@ -74,19 +74,20 @@ static bool mi_page_is_valid_init(mi_page_t* page) {
   mi_assert_internal(page->used <= page->capacity);
   mi_assert_internal(page->capacity <= page->reserved);
 
-  const size_t bsize = mi_page_block_size(page);
   mi_segment_t* segment = _mi_page_segment(page);
   uint8_t* start = _mi_page_start(segment,page,NULL);
-  mi_assert_internal(start == _mi_segment_page_start(segment,page,bsize,NULL,NULL));
+  mi_assert_internal(start == _mi_segment_page_start(segment,page,NULL));
+  //const size_t bsize = mi_page_block_size(page);
   //mi_assert_internal(start + page->capacity*page->block_size == page->top);
 
   mi_assert_internal(mi_page_list_is_valid(page,page->free));
   mi_assert_internal(mi_page_list_is_valid(page,page->local_free));
 
   #if MI_DEBUG>3 // generally too expensive to check this
-  if (page->flags.is_zero) {
-    for(mi_block_t* block = page->free; block != NULL; mi_block_next(page,block)) {
-      mi_assert_expensive(mi_mem_is_zero(block + 1, page->block_size - sizeof(mi_block_t)));
+  if (page->is_zero) {
+    const size_t ubsize = mi_page_usable_block_size(page);
+    for(mi_block_t* block = page->free; block != NULL; block = mi_block_next(page,block)) {
+      mi_assert_expensive(mi_mem_is_zero(block + 1, ubsize - sizeof(mi_block_t)));
     }
   }
   #endif
@@ -109,11 +110,12 @@ bool _mi_page_is_valid(mi_page_t* page) {
   #endif
   if (mi_page_heap(page)!=NULL) {
     mi_segment_t* segment = _mi_page_segment(page);
-    mi_assert_internal(!_mi_process_is_initialized || segment->thread_id == mi_page_heap(page)->thread_id || segment->thread_id==0);
-    if (segment->page_kind != MI_PAGE_HUGE) {
+
+    mi_assert_internal(!_mi_process_is_initialized || segment->thread_id==0 || segment->thread_id == mi_page_heap(page)->thread_id);
+    if (segment->kind != MI_SEGMENT_HUGE) {
       mi_page_queue_t* pq = mi_page_queue_of(page);
       mi_assert_internal(mi_page_queue_contains(pq, page));
-      mi_assert_internal(pq->block_size==mi_page_block_size(page) || mi_page_block_size(page) > MI_LARGE_OBJ_SIZE_MAX || mi_page_is_in_full(page));
+      mi_assert_internal(pq->block_size==mi_page_block_size(page) || mi_page_block_size(page) > MI_MEDIUM_OBJ_SIZE_MAX || mi_page_is_in_full(page));
       mi_assert_internal(mi_heap_contains_queue(mi_page_heap(page),pq));
     }
   }
@@ -122,11 +124,11 @@ bool _mi_page_is_valid(mi_page_t* page) {
 #endif
 
 void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never) {
-  mi_thread_free_t tfree;
   mi_thread_free_t tfreex;
   mi_delayed_t     old_delay;
+  mi_thread_free_t tfree;  
   do {
-    tfree = mi_atomic_read(&page->xthread_free);  // note: must acquire as we can break this loop and not do a CAS
+    tfree = mi_atomic_load_acquire(&page->xthread_free); // note: must acquire as we can break/repeat this loop and not do a CAS;
     tfreex = mi_tf_set_delayed(tfree, delay);
     old_delay = mi_tf_delayed(tfree);
     if (mi_unlikely(old_delay == MI_DELAYED_FREEING)) {
@@ -140,7 +142,7 @@ void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool overrid
       break; // leave never-delayed flag set
     }
   } while ((old_delay == MI_DELAYED_FREEING) ||
-           !mi_atomic_cas_weak(&page->xthread_free, tfreex, tfree));
+           !mi_atomic_cas_weak_release(&page->xthread_free, &tfree, tfreex));
 }
 
 /* -----------------------------------------------------------
@@ -154,13 +156,12 @@ void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool overrid
 static void _mi_page_thread_free_collect(mi_page_t* page)
 {
   mi_block_t* head;
-  mi_thread_free_t tfree;
   mi_thread_free_t tfreex;
+  mi_thread_free_t tfree = mi_atomic_load_relaxed(&page->xthread_free);
   do {
-    tfree = mi_atomic_read_relaxed(&page->xthread_free);
     head = mi_tf_block(tfree);
     tfreex = mi_tf_set_block(tfree,NULL);
-  } while (!mi_atomic_cas_weak(&page->xthread_free, tfreex, tfree));
+  } while (!mi_atomic_cas_weak_acq_rel(&page->xthread_free, &tfree, tfreex));
 
   // return if the list is empty
   if (head == NULL) return;
@@ -230,9 +231,10 @@ void _mi_page_free_collect(mi_page_t* page, bool force) {
 // called from segments when reclaiming abandoned pages
 void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page) {
   mi_assert_expensive(mi_page_is_valid_init(page));
+
   mi_assert_internal(mi_page_heap(page) == heap);
   mi_assert_internal(mi_page_thread_free_flag(page) != MI_NEVER_DELAYED_FREE);
-  mi_assert_internal(_mi_page_segment(page)->page_kind != MI_PAGE_HUGE);
+  mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE);
   mi_assert_internal(!page->is_reset);
   // TODO: push on full queue immediately if it is full?
   mi_page_queue_t* pq = mi_page_queue(heap, mi_page_block_size(page));
@@ -243,16 +245,14 @@ void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page) {
 // allocate a fresh page from a segment
 static mi_page_t* mi_page_fresh_alloc(mi_heap_t* heap, mi_page_queue_t* pq, size_t block_size) {
   mi_assert_internal(pq==NULL||mi_heap_contains_queue(heap, pq));
-  mi_assert_internal(pq==NULL||block_size == pq->block_size);
   mi_page_t* page = _mi_segment_page_alloc(heap, block_size, &heap->tld->segments, &heap->tld->os);
   if (page == NULL) {
     // this may be out-of-memory, or an abandoned page was reclaimed (and in our queue)
     return NULL;
   }
-  // a fresh page was found, initialize it
-  mi_assert_internal(pq==NULL || _mi_page_segment(page)->page_kind != MI_PAGE_HUGE);
+  mi_assert_internal(pq==NULL || _mi_page_segment(page)->kind != MI_SEGMENT_HUGE);
   mi_page_init(heap, page, block_size, heap->tld);
-  _mi_stat_increase(&heap->tld->stats.pages, 1);
+  mi_heap_stat_increase(heap, pages, 1);
   if (pq!=NULL) mi_page_queue_push(heap, pq, page); // huge pages use pq==NULL
   mi_assert_expensive(_mi_page_is_valid(page));
   return page;
@@ -273,11 +273,9 @@ static mi_page_t* mi_page_fresh(mi_heap_t* heap, mi_page_queue_t* pq) {
    (put there by other threads if they deallocated in a full page)
 ----------------------------------------------------------- */
 void _mi_heap_delayed_free(mi_heap_t* heap) {
-  // take over the list (note: no atomic exchange is it is often NULL)
-  mi_block_t* block;
-  do {
-    block = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
-  } while (block != NULL && !mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, NULL, block));
+  // take over the list (note: no atomic exchange since it is often NULL)
+  mi_block_t* block = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free);
+  while (block != NULL && !mi_atomic_cas_ptr_weak_acq_rel(mi_block_t, &heap->thread_delayed_free, &block, NULL)) { /* nothing */ };
 
   // and free them all
   while(block != NULL) {
@@ -286,11 +284,10 @@ void _mi_heap_delayed_free(mi_heap_t* heap) {
     if (!_mi_free_delayed_block(block)) {
       // we might already start delayed freeing while another thread has not yet
       // reset the delayed_freeing flag; in that case delay it further by reinserting.
-      mi_block_t* dfree;
+      mi_block_t* dfree = mi_atomic_load_ptr_relaxed(mi_block_t, &heap->thread_delayed_free);
       do {
-        dfree = mi_atomic_read_ptr_relaxed(mi_block_t,&heap->thread_delayed_free);
         mi_block_set_nextx(heap, block, dfree, heap->keys);
-      } while (!mi_atomic_cas_ptr_weak(mi_block_t,&heap->thread_delayed_free, block, dfree));
+      } while (!mi_atomic_cas_ptr_weak_release(mi_block_t,&heap->thread_delayed_free, &dfree, block));
     }
     block = next;
   }
@@ -370,9 +367,11 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) {
   // no more aligned blocks in here
   mi_page_set_has_aligned(page, false);
 
+  mi_heap_t* heap = mi_page_heap(page);
+
   // remove from the page list
   // (no need to do _mi_heap_delayed_free first as all blocks are already free)
-  mi_segments_tld_t* segments_tld = &mi_page_heap(page)->tld->segments;
+  mi_segments_tld_t* segments_tld = &heap->tld->segments;
   mi_page_queue_remove(pq, page);
 
   // and free it
@@ -380,7 +379,8 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) {
   _mi_segment_page_free(page, force, segments_tld);
 }
 
-#define MI_MAX_RETIRE_SIZE    MI_LARGE_OBJ_SIZE_MAX  
+// Retire parameters
+#define MI_MAX_RETIRE_SIZE    MI_MEDIUM_OBJ_SIZE_MAX  
 #define MI_RETIRE_CYCLES      (8)
 
 // Retire a page with no more used blocks
@@ -389,11 +389,11 @@ void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force) {
 // Note: called from `mi_free` and benchmarks often
 // trigger this due to freeing everything and then
 // allocating again so careful when changing this.
-void _mi_page_retire(mi_page_t* page) {
+void _mi_page_retire(mi_page_t* page) mi_attr_noexcept {
   mi_assert_internal(page != NULL);
   mi_assert_expensive(_mi_page_is_valid(page));
   mi_assert_internal(mi_page_all_free(page));
-
+  
   mi_page_set_has_aligned(page, false);
 
   // don't retire too often..
@@ -406,7 +406,7 @@ void _mi_page_retire(mi_page_t* page) {
   if (mi_likely(page->xblock_size <= MI_MAX_RETIRE_SIZE && !mi_page_is_in_full(page))) {
     if (pq->last==page && pq->first==page) { // the only page in the queue?
       mi_stat_counter_increase(_mi_stats_main.page_no_retire,1);
-      page->retire_expire = (page->xblock_size <= MI_SMALL_OBJ_SIZE_MAX ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4);
+      page->retire_expire = 1 + (page->xblock_size <= MI_SMALL_OBJ_SIZE_MAX ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4);      
       mi_heap_t* heap = mi_page_heap(page);
       mi_assert_internal(pq >= heap->pages);
       const size_t index = pq - heap->pages;
@@ -417,7 +417,6 @@ void _mi_page_retire(mi_page_t* page) {
       return; // dont't free after all
     }
   }
-
   _mi_page_free(page, pq, false);
 }
 
@@ -462,7 +461,7 @@ void _mi_heap_collect_retired(mi_heap_t* heap, bool force) {
 #define MI_MIN_SLICES       (2)
 
 static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats) {
-  UNUSED(stats);
+  MI_UNUSED(stats);
   #if (MI_SECURE<=2)
   mi_assert_internal(page->free == NULL);
   mi_assert_internal(page->local_free == NULL);
@@ -520,7 +519,7 @@ static void mi_page_free_list_extend_secure(mi_heap_t* const heap, mi_page_t* co
 
 static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, const size_t bsize, const size_t extend, mi_stats_t* const stats)
 {
-  UNUSED(stats);
+  MI_UNUSED(stats);
   #if (MI_SECURE <= 2)
   mi_assert_internal(page->free == NULL);
   mi_assert_internal(page->local_free == NULL);
@@ -561,6 +560,7 @@ static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, co
 // allocations but this did not speed up any benchmark (due to an
 // extra test in malloc? or cache effects?)
 static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) {
+  MI_UNUSED(tld); 
   mi_assert_expensive(mi_page_is_valid_init(page));
   #if (MI_SECURE<=2)
   mi_assert(page->free == NULL);
@@ -570,20 +570,22 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld)
   if (page->capacity >= page->reserved) return;
 
   size_t page_size;
-  //uint8_t* page_start = 
   _mi_page_start(_mi_page_segment(page), page, &page_size);
   mi_stat_counter_increase(tld->stats.pages_extended, 1);
 
   // calculate the extend count
   const size_t bsize = (page->xblock_size < MI_HUGE_BLOCK_SIZE ? page->xblock_size : page_size);
   size_t extend = page->reserved - page->capacity;
-  size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize);
-  if (max_extend < MI_MIN_EXTEND) max_extend = MI_MIN_EXTEND;
+  mi_assert_internal(extend > 0);
 
+  size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize);
+  if (max_extend < MI_MIN_EXTEND) { max_extend = MI_MIN_EXTEND; }
+  mi_assert_internal(max_extend > 0);
+    
   if (extend > max_extend) {
     // ensure we don't touch memory beyond the page to reduce page commit.
     // the `lean` benchmark tests this. Going from 1 to 8 increases rss by 50%.
-    extend = (max_extend==0 ? 1 : max_extend);
+    extend = max_extend;
   }
 
   mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved);
@@ -615,17 +617,25 @@ static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi
   mi_assert_internal(block_size > 0);
   // set fields
   mi_page_set_heap(page, heap);
+  page->xblock_size = (block_size < MI_HUGE_BLOCK_SIZE ? (uint32_t)block_size : MI_HUGE_BLOCK_SIZE); // initialize before _mi_segment_page_start
   size_t page_size;
-  _mi_segment_page_start(segment, page, block_size, &page_size, NULL);
-  page->xblock_size = (block_size < MI_HUGE_BLOCK_SIZE ? (uint32_t)block_size : MI_HUGE_BLOCK_SIZE);
+  _mi_segment_page_start(segment, page, &page_size);
+  mi_assert_internal(mi_page_block_size(page) <= page_size);
+  mi_assert_internal(page_size <= page->slice_count*MI_SEGMENT_SLICE_SIZE);
   mi_assert_internal(page_size / block_size < (1L<<16));
   page->reserved = (uint16_t)(page_size / block_size);
   #ifdef MI_ENCODE_FREELIST
   page->keys[0] = _mi_heap_random_next(heap);
   page->keys[1] = _mi_heap_random_next(heap);
   #endif
+  #if MI_DEBUG > 0
+  page->is_zero = false; // ensure in debug mode we initialize with MI_DEBUG_UNINIT, see issue #501
+  #else
   page->is_zero = page->is_zero_init;
+  #endif
 
+  mi_assert_internal(page->is_committed);
+  mi_assert_internal(!page->is_reset);
   mi_assert_internal(page->capacity == 0);
   mi_assert_internal(page->free == NULL);
   mi_assert_internal(page->used == 0);
@@ -684,10 +694,10 @@ static mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, mi_page_queue_t* p
     page = next;
   } // for each page
 
-  mi_stat_counter_increase(heap->tld->stats.searches, count);
+  mi_heap_stat_counter_increase(heap, searches, count);
 
   if (page == NULL) {
-    _mi_heap_collect_retired(heap, false); // perhaps make a page available
+    _mi_heap_collect_retired(heap, false); // perhaps make a page available?
     page = mi_page_fresh(heap, pq);
     if (page == NULL && first_try) {
       // out-of-memory _or_ an abandoned page with free blocks was reclaimed, try once again
@@ -709,14 +719,17 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) {
   mi_page_queue_t* pq = mi_page_queue(heap,size);
   mi_page_t* page = pq->first;
   if (page != NULL) {
-    if ((MI_SECURE >= 3) && page->capacity < page->reserved && ((_mi_heap_random_next(heap) & 1) == 1)) {
-      // in secure mode, we extend half the time to increase randomness
+   #if (MI_SECURE>=3) // in secure mode, we extend half the time to increase randomness      
+    if (page->capacity < page->reserved && ((_mi_heap_random_next(heap) & 1) == 1)) {
       mi_page_extend_free(heap, page, heap->tld);
       mi_assert_internal(mi_page_immediate_available(page));
     }
-    else {
+    else 
+   #endif
+    {
       _mi_page_free_collect(page,false);
     }
+    
     if (mi_page_immediate_available(page)) {
       page->retire_expire = 0;
       return page; // fast path
@@ -734,20 +747,20 @@ static inline mi_page_t* mi_find_free_page(mi_heap_t* heap, size_t size) {
 ----------------------------------------------------------- */
 
 static mi_deferred_free_fun* volatile deferred_free = NULL;
-static volatile _Atomic(void*) deferred_arg; // = NULL
+static _Atomic(void*) deferred_arg; // = NULL
 
 void _mi_deferred_free(mi_heap_t* heap, bool force) {
   heap->tld->heartbeat++;
   if (deferred_free != NULL && !heap->tld->recurse) {
     heap->tld->recurse = true;
-    deferred_free(force, heap->tld->heartbeat, mi_atomic_read_ptr_relaxed(void,&deferred_arg));
+    deferred_free(force, heap->tld->heartbeat, mi_atomic_load_ptr_relaxed(void,&deferred_arg));
     heap->tld->recurse = false;
   }
 }
 
 void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noexcept {
   deferred_free = fn;
-  mi_atomic_write_ptr(void,&deferred_arg, arg);
+  mi_atomic_store_ptr_release(void,&deferred_arg, arg);
 }
 
 
@@ -755,30 +768,39 @@ void mi_register_deferred_free(mi_deferred_free_fun* fn, void* arg) mi_attr_noex
   General allocation
 ----------------------------------------------------------- */
 
-// A huge page is allocated directly without being in a queue.
+// Large and huge page allocation.
+// Huge pages are allocated directly without being in a queue.
 // Because huge pages contain just one block, and the segment contains
 // just that page, we always treat them as abandoned and any thread
 // that frees the block can free the whole page and segment directly.
-static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) {
+static mi_page_t* mi_large_huge_page_alloc(mi_heap_t* heap, size_t size) {
   size_t block_size = _mi_os_good_alloc_size(size);
-  mi_assert_internal(_mi_bin(block_size) == MI_BIN_HUGE);
-  mi_page_t* page = mi_page_fresh_alloc(heap,NULL,block_size);
+  mi_assert_internal(mi_bin(block_size) == MI_BIN_HUGE);
+  bool is_huge = (block_size > MI_LARGE_OBJ_SIZE_MAX);
+  mi_page_queue_t* pq = (is_huge ? NULL : mi_page_queue(heap, block_size));
+  mi_page_t* page = mi_page_fresh_alloc(heap, pq, block_size);
   if (page != NULL) {
-    const size_t bsize = mi_page_block_size(page);  // note: not `mi_page_usable_block_size` as `size` includes padding already
-    mi_assert_internal(bsize >= size);
     mi_assert_internal(mi_page_immediate_available(page));
-    mi_assert_internal(_mi_page_segment(page)->page_kind==MI_PAGE_HUGE);
-    mi_assert_internal(_mi_page_segment(page)->used==1);
-    mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue
-    mi_page_set_heap(page, NULL);
-
-    if (bsize > MI_HUGE_OBJ_SIZE_MAX) {
-      _mi_stat_increase(&heap->tld->stats.giant, bsize);
-      _mi_stat_counter_increase(&heap->tld->stats.giant_count, 1);
+    
+    if (pq == NULL) {
+      // huge pages are directly abandoned
+      mi_assert_internal(_mi_page_segment(page)->kind == MI_SEGMENT_HUGE);
+      mi_assert_internal(_mi_page_segment(page)->used==1);
+      mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue
+      mi_page_set_heap(page, NULL);
+    }
+    else {
+      mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE);
+    }
+    
+    const size_t bsize = mi_page_usable_block_size(page);  // note: not `mi_page_block_size` to account for padding
+    if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
+      mi_heap_stat_increase(heap, large, bsize);
+      mi_heap_stat_counter_increase(heap, large_count, 1);
     }
     else {
-      _mi_stat_increase(&heap->tld->stats.huge, bsize);
-      _mi_stat_counter_increase(&heap->tld->stats.huge_count, 1);
+      mi_heap_stat_increase(heap, huge, bsize);
+      mi_heap_stat_counter_increase(heap, huge_count, 1);
     }
   }
   return page;
@@ -790,13 +812,13 @@ static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size) {
 static mi_page_t* mi_find_page(mi_heap_t* heap, size_t size) mi_attr_noexcept {
   // huge allocation?
   const size_t req_size = size - MI_PADDING_SIZE;  // correct for padding_size in case of an overflow on `size`  
-  if (mi_unlikely(req_size > (MI_LARGE_OBJ_SIZE_MAX - MI_PADDING_SIZE) )) {
+  if (mi_unlikely(req_size > (MI_MEDIUM_OBJ_SIZE_MAX - MI_PADDING_SIZE) )) {
     if (mi_unlikely(req_size > PTRDIFF_MAX)) {  // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)
       _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size);
       return NULL;
     }
     else {
-      return mi_huge_page_alloc(heap,size);
+      return mi_large_huge_page_alloc(heap,size);
     }
   }
   else {
index 2a96ccf618a2abc9c8ac307c95fedb3a19c1a3cb..d474a53a04b1d87fff0e5bfb0c49788ab530b1d0 100644 (file)
@@ -1,9 +1,13 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2019, Microsoft Research, Daan Leijen
+Copyright (c) 2019-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
 -----------------------------------------------------------------------------*/
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE   // for syscall() on Linux
+#endif
+
 #include "mimalloc.h"
 #include "mimalloc-internal.h"
 
@@ -115,7 +119,7 @@ static void chacha_init(mi_random_ctx_t* ctx, const uint8_t key[32], uint64_t no
 
 static void chacha_split(mi_random_ctx_t* ctx, uint64_t nonce, mi_random_ctx_t* ctx_new) {
   memset(ctx_new, 0, sizeof(*ctx_new));
-  memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input));
+  _mi_memcpy(ctx_new->input, ctx->input, sizeof(ctx_new->input));
   ctx_new->input[12] = 0;
   ctx_new->input[13] = 0;
   ctx_new->input[14] = (uint32_t)nonce;
@@ -155,37 +159,69 @@ uintptr_t _mi_random_next(mi_random_ctx_t* ctx) {
 
 /* ----------------------------------------------------------------------------
 To initialize a fresh random context we rely on the OS:
-- Windows     : BCryptGenRandom
-- osX,bsd,wasi: arc4random_buf
+- Windows     : BCryptGenRandom (or RtlGenRandom)
+- macOS       : CCRandomGenerateBytes, arc4random_buf
+- bsd,wasi    : arc4random_buf
 - Linux       : getrandom,/dev/urandom
 If we cannot get good randomness, we fall back to weak randomness based on a timer and ASLR.
 -----------------------------------------------------------------------------*/
 
 #if defined(_WIN32)
+
+#if defined(MI_USE_RTLGENRANDOM) || defined(__cplusplus)
+// We prefer to use BCryptGenRandom instead of (the unofficial) RtlGenRandom but when using 
+// dynamic overriding, we observed it can raise an exception when compiled with C++, and 
+// sometimes deadlocks when also running under the VS debugger.
+#pragma comment (lib,"advapi32.lib")
+#define RtlGenRandom  SystemFunction036
+#ifdef __cplusplus
+extern "C" {
+#endif
+BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
+#ifdef __cplusplus
+}
+#endif
+static bool os_random_buf(void* buf, size_t buf_len) {
+  return (RtlGenRandom(buf, (ULONG)buf_len) != 0);
+}
+#else
 #pragma comment (lib,"bcrypt.lib")
 #include <bcrypt.h>
 static bool os_random_buf(void* buf, size_t buf_len) {
   return (BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)buf_len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0);
 }
-/*
-#define SystemFunction036 NTAPI SystemFunction036
-#include <NTSecAPI.h>
-#undef SystemFunction036
+#endif
+
+#elif defined(__APPLE__)
+#include <AvailabilityMacros.h>
+#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
+#include <CommonCrypto/CommonCryptoError.h>
+#include <CommonCrypto/CommonRandom.h>
+#endif
 static bool os_random_buf(void* buf, size_t buf_len) {
-  RtlGenRandom(buf, (ULONG)buf_len);
-  return true;
+  #if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
+    // We prefere CCRandomGenerateBytes as it returns an error code while arc4random_buf
+    // may fail silently on macOS. See PR #390, and <https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen/FreeBSD/arc4random.c.auto.html>      
+    return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess);
+  #else
+    // fall back on older macOS
+    arc4random_buf(buf, buf_len);
+    return true;
+  #endif
 }
-*/
-#elif defined(ANDROID) || defined(XP_DARWIN) || defined(__APPLE__) || defined(__DragonFly__) || \
+
+#elif defined(__ANDROID__) || defined(__DragonFly__) || \
       defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
-      defined(__sun) || defined(__wasi__)
+      defined(__sun) // todo: what to use with __wasi__?
 #include <stdlib.h>
 static bool os_random_buf(void* buf, size_t buf_len) {
   arc4random_buf(buf, buf_len);
   return true;
 }
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__HAIKU__)
+#if defined(__linux__)
 #include <sys/syscall.h>
+#endif
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -200,12 +236,12 @@ static bool os_random_buf(void* buf, size_t buf_len) {
   #ifndef GRND_NONBLOCK
   #define GRND_NONBLOCK (1)
   #endif
-  static volatile _Atomic(uintptr_t) no_getrandom; // = 0
-  if (mi_atomic_read(&no_getrandom)==0) {
+  static _Atomic(uintptr_t) no_getrandom; // = 0
+  if (mi_atomic_load_acquire(&no_getrandom)==0) {
     ssize_t ret = syscall(SYS_getrandom, buf, buf_len, GRND_NONBLOCK);
     if (ret >= 0) return (buf_len == (size_t)ret);
-    if (ret != ENOSYS) return false;
-    mi_atomic_write(&no_getrandom,1); // don't call again, and fall back to /dev/urandom
+    if (errno != ENOSYS) return false;
+    mi_atomic_store_release(&no_getrandom, 1UL); // don't call again, and fall back to /dev/urandom
   }
 #endif
   int flags = O_RDONLY;
@@ -241,8 +277,9 @@ static bool os_random_buf(void* buf, size_t buf_len) {
 #include <time.h>
 #endif
 
-uintptr_t _os_random_weak(uintptr_t extra_seed) {
-  uintptr_t x = (uintptr_t)&_os_random_weak ^ extra_seed; // ASLR makes the address random
+uintptr_t _mi_os_random_weak(uintptr_t extra_seed) {
+  uintptr_t x = (uintptr_t)&_mi_os_random_weak ^ extra_seed; // ASLR makes the address random
+  
   #if defined(_WIN32)
     LARGE_INTEGER pcount;
     QueryPerformanceCounter(&pcount);
@@ -269,8 +306,10 @@ void _mi_random_init(mi_random_ctx_t* ctx) {
   if (!os_random_buf(key, sizeof(key))) {
     // if we fail to get random data from the OS, we fall back to a
     // weak random source based on the current time
+    #if !defined(__wasi__)
     _mi_warning_message("unable to use secure randomness\n");
-    uintptr_t x = _os_random_weak(0);
+    #endif
+    uintptr_t x = _mi_os_random_weak(0);
     for (size_t i = 0; i < 8; i++) {  // key is eight 32-bit words.
       x = _mi_random_shuffle(x);
       ((uint32_t*)key)[i] = (uint32_t)x;
index ae3a799acd0869279b2e6994f8123ab1a4b21f97..72ce84947d5befbcd7989a4f9ec52c6bd8dbe9c3 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2019, Microsoft Research, Daan Leijen
+Copyright (c) 2019-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -37,10 +37,10 @@ Possible issues:
 
 #include <string.h>  // memset
 
-#include "bitmap.inc.c"
+#include "bitmap.h"
 
 // Internal raw OS interface
-size_t  _mi_os_large_page_size();
+size_t  _mi_os_large_page_size(void);
 bool    _mi_os_protect(void* addr, size_t size);
 bool    _mi_os_unprotect(void* addr, size_t size);
 bool    _mi_os_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
@@ -50,16 +50,16 @@ bool    _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
 
 // arena.c
 void    _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats);
-void*   _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
-void*   _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
+void*   _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
+void*   _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
 
 
 
 // Constants
 #if (MI_INTPTR_SIZE==8)
-#define MI_HEAP_REGION_MAX_SIZE    (256 * GiB)  // 64KiB for the region map 
+#define MI_HEAP_REGION_MAX_SIZE    (256 * MI_GiB)  // 64KiB for the region map 
 #elif (MI_INTPTR_SIZE==4)
-#define MI_HEAP_REGION_MAX_SIZE    (3 * GiB)    // ~ KiB for the region map
+#define MI_HEAP_REGION_MAX_SIZE    (3 * MI_GiB)    // ~ KiB for the region map
 #else
 #error "define the maximum heap space allowed for regions on this platform"
 #endif
@@ -74,10 +74,11 @@ void*   _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, boo
 
 // Region info 
 typedef union mi_region_info_u {
-  uintptr_t value;      
+  size_t value;      
   struct {
     bool  valid;        // initialized?
-    bool  is_large;     // allocated in fixed large/huge OS pages
+    bool  is_large:1;   // allocated in fixed large/huge OS pages
+    bool  is_pinned:1;  // pinned memory cannot be decommitted
     short numa_node;    // the associated NUMA node (where -1 means no associated node)
   } x;
 } mi_region_info_t;
@@ -86,21 +87,21 @@ typedef union mi_region_info_u {
 // A region owns a chunk of REGION_SIZE (256MiB) (virtual) memory with
 // a bit map with one bit per MI_SEGMENT_SIZE (4MiB) block.
 typedef struct mem_region_s {
-  volatile _Atomic(uintptr_t)        info;        // mi_region_info_t.value
-  volatile _Atomic(void*)            start;       // start of the memory area 
-  mi_bitmap_field_t                  in_use;      // bit per in-use block
-  mi_bitmap_field_t                  dirty;       // track if non-zero per block
-  mi_bitmap_field_t                  commit;      // track if committed per block
-  mi_bitmap_field_t                  reset;       // track if reset per block
-  volatile _Atomic(uintptr_t)        arena_memid; // if allocated from a (huge page) arena
-  uintptr_t                          padding;     // round to 8 fields
+  _Atomic(size_t)           info;        // mi_region_info_t.value
+  _Atomic(void*)            start;       // start of the memory area 
+  mi_bitmap_field_t         in_use;      // bit per in-use block
+  mi_bitmap_field_t         dirty;       // track if non-zero per block
+  mi_bitmap_field_t         commit;      // track if committed per block
+  mi_bitmap_field_t         reset;       // track if reset per block
+  _Atomic(size_t)           arena_memid; // if allocated from a (huge page) arena
+  _Atomic(size_t)           padding;     // round to 8 fields (needs to be atomic for msvc, see issue #508)
 } mem_region_t;
 
 // The region map
 static mem_region_t regions[MI_REGION_MAX];
 
 // Allocated regions
-static volatile _Atomic(uintptr_t) regions_count; // = 0;        
+static _Atomic(size_t) regions_count; // = 0;        
 
 
 /* ----------------------------------------------------------------------------
@@ -121,11 +122,11 @@ static size_t mi_good_commit_size(size_t size) {
 */
 
 // Return if a pointer points into a region reserved by us.
-bool mi_is_in_heap_region(const void* p) mi_attr_noexcept {
+mi_decl_nodiscard bool mi_is_in_heap_region(const void* p) mi_attr_noexcept {
   if (p==NULL) return false;
-  size_t count = mi_atomic_read_relaxed(&regions_count);
+  size_t count = mi_atomic_load_relaxed(&regions_count);
   for (size_t i = 0; i < count; i++) {
-    uint8_t* start = mi_atomic_read_ptr_relaxed(uint8_t,&regions[i].start);
+    uint8_t* start = (uint8_t*)mi_atomic_load_ptr_relaxed(uint8_t, &regions[i].start);
     if (start != NULL && (uint8_t*)p >= start && (uint8_t*)p < start + MI_REGION_SIZE) return true;
   }
   return false;
@@ -133,7 +134,7 @@ bool mi_is_in_heap_region(const void* p) mi_attr_noexcept {
 
 
 static void* mi_region_blocks_start(const mem_region_t* region, mi_bitmap_index_t bit_idx) {
-  uint8_t* start = mi_atomic_read_ptr(uint8_t,&region->start);
+  uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t, &((mem_region_t*)region)->start);
   mi_assert_internal(start != NULL);
   return (start + (bit_idx * MI_SEGMENT_SIZE));  
 }
@@ -171,45 +172,47 @@ static bool mi_memid_is_arena(size_t id, mem_region_t** region, mi_bitmap_index_
 static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld)
 {
   // not out of regions yet?
-  if (mi_atomic_read_relaxed(&regions_count) >= MI_REGION_MAX - 1) return false;
+  if (mi_atomic_load_relaxed(&regions_count) >= MI_REGION_MAX - 1) return false;
 
   // try to allocate a fresh region from the OS
   bool region_commit = (commit && mi_option_is_enabled(mi_option_eager_region_commit));
   bool region_large = (commit && allow_large);
   bool is_zero = false;
+  bool is_pinned = false;
   size_t arena_memid = 0;
-  void* const start = _mi_arena_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, &region_commit, &region_large, &is_zero, &arena_memid, tld);
+  void* const start = _mi_arena_alloc_aligned(MI_REGION_SIZE, MI_SEGMENT_ALIGN, &region_commit, &region_large, &is_pinned, &is_zero, &arena_memid, tld);
   if (start == NULL) return false;
   mi_assert_internal(!(region_large && !allow_large));
   mi_assert_internal(!region_large || region_commit);
 
   // claim a fresh slot
-  const uintptr_t idx = mi_atomic_increment(&regions_count);
+  const size_t idx = mi_atomic_increment_acq_rel(&regions_count);
   if (idx >= MI_REGION_MAX) {
-    mi_atomic_decrement(&regions_count);
+    mi_atomic_decrement_acq_rel(&regions_count);
     _mi_arena_free(start, MI_REGION_SIZE, arena_memid, region_commit, tld->stats);
-    _mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, GiB));
+    _mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, MI_GiB));
     return false;
   }
 
   // allocated, initialize and claim the initial blocks
   mem_region_t* r = &regions[idx];
   r->arena_memid  = arena_memid;
-  mi_atomic_write(&r->in_use, 0);
-  mi_atomic_write(&r->dirty, (is_zero ? 0 : MI_BITMAP_FIELD_FULL));
-  mi_atomic_write(&r->commit, (region_commit ? MI_BITMAP_FIELD_FULL : 0));
-  mi_atomic_write(&r->reset, 0);
+  mi_atomic_store_release(&r->in_use, (size_t)0);
+  mi_atomic_store_release(&r->dirty, (is_zero ? 0 : MI_BITMAP_FIELD_FULL));
+  mi_atomic_store_release(&r->commit, (region_commit ? MI_BITMAP_FIELD_FULL : 0));
+  mi_atomic_store_release(&r->reset, (size_t)0);
   *bit_idx = 0;
-  mi_bitmap_claim(&r->in_use, 1, blocks, *bit_idx, NULL);
-  mi_atomic_write_ptr(uint8_t*,&r->start, start);
+  _mi_bitmap_claim(&r->in_use, 1, blocks, *bit_idx, NULL);
+  mi_atomic_store_ptr_release(void,&r->start, start);
 
   // and share it 
   mi_region_info_t info;
   info.value = 0;                        // initialize the full union to zero
   info.x.valid = true;
   info.x.is_large = region_large;
+  info.x.is_pinned = is_pinned;
   info.x.numa_node = (short)_mi_os_numa_node(tld);
-  mi_atomic_write(&r->info, info.value); // now make it available to others
+  mi_atomic_store_release(&r->info, info.value); // now make it available to others
   *region = r;
   return true;
 }
@@ -221,7 +224,7 @@ static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large,
 static bool mi_region_is_suitable(const mem_region_t* region, int numa_node, bool allow_large ) {
   // initialized at all?
   mi_region_info_t info;
-  info.value = mi_atomic_read_relaxed(&region->info);
+  info.value = mi_atomic_load_relaxed(&((mem_region_t*)region)->info);
   if (info.value==0) return false;
 
   // numa correct
@@ -240,7 +243,7 @@ static bool mi_region_is_suitable(const mem_region_t* region, int numa_node, boo
 static bool mi_region_try_claim(int numa_node, size_t blocks, bool allow_large, mem_region_t** region, mi_bitmap_index_t* bit_idx, mi_os_tld_t* tld)
 {
   // try all regions for a free slot  
-  const size_t count = mi_atomic_read(&regions_count);
+  const size_t count = mi_atomic_load_relaxed(&regions_count); // monotonic, so ok to be relaxed
   size_t idx = tld->region_idx; // Or start at 0 to reuse low addresses? Starting at 0 seems to increase latency though
   for (size_t visited = 0; visited < count; visited++, idx++) {
     if (idx >= count) idx = 0;  // wrap around
@@ -248,7 +251,7 @@ static bool mi_region_try_claim(int numa_node, size_t blocks, bool allow_large,
     // if this region suits our demand (numa node matches, large OS page matches)
     if (mi_region_is_suitable(r, numa_node, allow_large)) {
       // then try to atomically claim a segment(s) in this region
-      if (mi_bitmap_try_find_claim_field(&r->in_use, 0, blocks, bit_idx)) {
+      if (_mi_bitmap_try_find_claim_field(&r->in_use, 0, blocks, bit_idx)) {
         tld->region_idx = idx;    // remember the last found position
         *region = r;
         return true;
@@ -259,16 +262,16 @@ static bool mi_region_try_claim(int numa_node, size_t blocks, bool allow_large,
 }
 
 
-static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
 {
   mi_assert_internal(blocks <= MI_BITMAP_FIELD_BITS);
   mem_region_t* region;
   mi_bitmap_index_t bit_idx;
   const int numa_node = (_mi_os_numa_node_count() <= 1 ? -1 : _mi_os_numa_node(tld));
   // try to claim in existing regions
-  if (!mi_region_try_claim(numa_node, blocks, *is_large, &region, &bit_idx, tld)) {
+  if (!mi_region_try_claim(numa_node, blocks, *large, &region, &bit_idx, tld)) {
     // otherwise try to allocate a fresh region and claim in there
-    if (!mi_region_try_alloc_os(blocks, *commit, *is_large, &region, &bit_idx, tld)) {
+    if (!mi_region_try_alloc_os(blocks, *commit, *large, &region, &bit_idx, tld)) {
       // out of regions or memory
       return NULL;
     }
@@ -277,41 +280,46 @@ static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bo
   // ------------------------------------------------
   // found a region and claimed `blocks` at `bit_idx`, initialize them now
   mi_assert_internal(region != NULL);
-  mi_assert_internal(mi_bitmap_is_claimed(&region->in_use, 1, blocks, bit_idx));
+  mi_assert_internal(_mi_bitmap_is_claimed(&region->in_use, 1, blocks, bit_idx));
 
   mi_region_info_t info;
-  info.value = mi_atomic_read(&region->info);
-  uint8_t* start = mi_atomic_read_ptr(uint8_t,&region->start);
-  mi_assert_internal(!(info.x.is_large && !*is_large));
+  info.value = mi_atomic_load_acquire(&region->info);
+  uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,&region->start);
+  mi_assert_internal(!(info.x.is_large && !*large));
   mi_assert_internal(start != NULL);
 
-  *is_zero = mi_bitmap_claim(&region->dirty, 1, blocks, bit_idx, NULL);  
-  *is_large = info.x.is_large;
-  *memid = mi_memid_create(region, bit_idx);
+  *is_zero   = _mi_bitmap_claim(&region->dirty, 1, blocks, bit_idx, NULL);  
+  *large     = info.x.is_large;
+  *is_pinned = info.x.is_pinned;
+  *memid     = mi_memid_create(region, bit_idx);
   void* p = start + (mi_bitmap_index_bit_in_field(bit_idx) * MI_SEGMENT_SIZE);
 
   // commit
   if (*commit) {
     // ensure commit
     bool any_uncommitted;
-    mi_bitmap_claim(&region->commit, 1, blocks, bit_idx, &any_uncommitted);
+    _mi_bitmap_claim(&region->commit, 1, blocks, bit_idx, &any_uncommitted);
     if (any_uncommitted) {
-      mi_assert_internal(!info.x.is_large);
-      bool commit_zero;
-      _mi_mem_commit(p, blocks * MI_SEGMENT_SIZE, &commit_zero, tld);
-      if (commit_zero) *is_zero = true;
+      mi_assert_internal(!info.x.is_large && !info.x.is_pinned);
+      bool commit_zero = false;
+      if (!_mi_mem_commit(p, blocks * MI_SEGMENT_SIZE, &commit_zero, tld)) {
+        // failed to commit! unclaim and return
+        mi_bitmap_unclaim(&region->in_use, 1, blocks, bit_idx);
+        return NULL;
+      }
+      if (commit_zero) *is_zero = true;      
     }
   }
   else {
     // no need to commit, but check if already fully committed
-    *commit = mi_bitmap_is_claimed(&region->commit, 1, blocks, bit_idx);
+    *commit = _mi_bitmap_is_claimed(&region->commit, 1, blocks, bit_idx);
   }  
-  mi_assert_internal(!*commit || mi_bitmap_is_claimed(&region->commit, 1, blocks, bit_idx));
+  mi_assert_internal(!*commit || _mi_bitmap_is_claimed(&region->commit, 1, blocks, bit_idx));
 
   // unreset reset blocks
-  if (mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx)) {
+  if (_mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx)) {
     // some blocks are still reset
-    mi_assert_internal(!info.x.is_large);
+    mi_assert_internal(!info.x.is_large && !info.x.is_pinned);
     mi_assert_internal(!mi_option_is_enabled(mi_option_eager_commit) || *commit || mi_option_get(mi_option_eager_commit_delay) > 0); 
     mi_bitmap_unclaim(&region->reset, 1, blocks, bit_idx);
     if (*commit || !mi_option_is_enabled(mi_option_reset_decommits)) { // only if needed
@@ -320,7 +328,7 @@ static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bo
       if (reset_zero) *is_zero = true;
     }
   }
-  mi_assert_internal(!mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx));
+  mi_assert_internal(!_mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx));
   
   #if (MI_DEBUG>=2)
   if (*commit) { ((uint8_t*)p)[0] = 0; }
@@ -338,12 +346,13 @@ static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bo
 
 // Allocate `size` memory aligned at `alignment`. Return non NULL on success, with a given memory `id`.
 // (`id` is abstract, but `id = idx*MI_REGION_MAP_BITS + bitidx`)
-void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
 {
   mi_assert_internal(memid != NULL && tld != NULL);
   mi_assert_internal(size > 0);
   *memid = 0;
   *is_zero = false;
+  *is_pinned = false;
   bool default_large = false;
   if (large==NULL) large = &default_large;  // ensure `large != NULL`  
   if (size == 0) return NULL;
@@ -354,14 +363,14 @@ void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* l
   size_t arena_memid;
   const size_t blocks = mi_region_block_count(size);
   if (blocks <= MI_REGION_MAX_OBJ_BLOCKS && alignment <= MI_SEGMENT_ALIGN) {
-    p = mi_region_try_alloc(blocks, commit, large, is_zero, memid, tld);    
+    p = mi_region_try_alloc(blocks, commit, large, is_pinned, is_zero, memid, tld);    
     if (p == NULL) {
       _mi_warning_message("unable to allocate from region: size %zu\n", size);
     }
   }
   if (p == NULL) {
     // and otherwise fall back to the OS
-    p = _mi_arena_alloc_aligned(size, alignment, commit, large, is_zero, &arena_memid, tld);
+    p = _mi_arena_alloc_aligned(size, alignment, commit, large, is_pinned, is_zero, &arena_memid, tld);
     *memid = mi_memid_create_from_arena(arena_memid);
   }
 
@@ -400,7 +409,7 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
     const size_t blocks = mi_region_block_count(size);
     mi_assert_internal(blocks + bit_idx <= MI_BITMAP_FIELD_BITS);
     mi_region_info_t info;
-    info.value = mi_atomic_read(&region->info);
+    info.value = mi_atomic_load_acquire(&region->info);
     mi_assert_internal(info.value != 0);
     void* blocks_start = mi_region_blocks_start(region, bit_idx);
     mi_assert_internal(blocks_start == p); // not a pointer in our area?
@@ -409,21 +418,21 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
 
     // committed?
     if (full_commit && (size % MI_SEGMENT_SIZE) == 0) {
-      mi_bitmap_claim(&region->commit, 1, blocks, bit_idx, NULL);
+      _mi_bitmap_claim(&region->commit, 1, blocks, bit_idx, NULL);
     }
 
     if (any_reset) {
       // set the is_reset bits if any pages were reset
-      mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, NULL);
+      _mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, NULL);
     }
 
     // reset the blocks to reduce the working set.
-    if (!info.x.is_large && mi_option_is_enabled(mi_option_segment_reset) 
+    if (!info.x.is_large && !info.x.is_pinned && mi_option_is_enabled(mi_option_segment_reset) 
        && (mi_option_is_enabled(mi_option_eager_commit) ||
            mi_option_is_enabled(mi_option_reset_decommits))) // cannot reset halfway committed segments, use only `option_page_reset` instead            
     {
       bool any_unreset;
-      mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, &any_unreset);
+      _mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, &any_unreset);
       if (any_unreset) {
         _mi_abandoned_await_readers(); // ensure no more pending write (in case reset = decommit)
         _mi_mem_reset(p, blocks * MI_SEGMENT_SIZE, tld);
@@ -432,7 +441,7 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
 
     // and unclaim
     bool all_unclaimed = mi_bitmap_unclaim(&region->in_use, 1, blocks, bit_idx);
-    mi_assert_internal(all_unclaimed); UNUSED(all_unclaimed);
+    mi_assert_internal(all_unclaimed); MI_UNUSED(all_unclaimed);
   }
 }
 
@@ -442,23 +451,21 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
 -----------------------------------------------------------------------------*/
 void _mi_mem_collect(mi_os_tld_t* tld) {
   // free every region that has no segments in use.
-  uintptr_t rcount = mi_atomic_read_relaxed(&regions_count);
+  size_t rcount = mi_atomic_load_relaxed(&regions_count);
   for (size_t i = 0; i < rcount; i++) {
     mem_region_t* region = &regions[i];
-    if (mi_atomic_read_relaxed(&region->info) != 0) {
+    if (mi_atomic_load_relaxed(&region->info) != 0) {
       // if no segments used, try to claim the whole region
-      uintptr_t m;
-      do {
-        m = mi_atomic_read_relaxed(&region->in_use);
-      } while(m == 0 && !mi_atomic_cas_weak(&region->in_use, MI_BITMAP_FIELD_FULL, 0 ));
+      size_t m = mi_atomic_load_relaxed(&region->in_use);
+      while (m == 0 && !mi_atomic_cas_weak_release(&region->in_use, &m, MI_BITMAP_FIELD_FULL)) { /* nothing */ };
       if (m == 0) {
         // on success, free the whole region
-        uint8_t* start = mi_atomic_read_ptr(uint8_t,&regions[i].start);
-        size_t arena_memid = mi_atomic_read_relaxed(&regions[i].arena_memid);
-        uintptr_t commit = mi_atomic_read_relaxed(&regions[i].commit);
-        memset(&regions[i], 0, sizeof(mem_region_t));
+        uint8_t* start = (uint8_t*)mi_atomic_load_ptr_acquire(uint8_t,&regions[i].start);
+        size_t arena_memid = mi_atomic_load_relaxed(&regions[i].arena_memid);
+        size_t commit = mi_atomic_load_relaxed(&regions[i].commit);
+        memset((void*)&regions[i], 0, sizeof(mem_region_t));  // cast to void* to avoid atomic warning
         // and release the whole region
-        mi_atomic_write(&region->info, 0);
+        mi_atomic_store_release(&region->info, (size_t)0);
         if (start != NULL) { // && !_mi_os_is_huge_reserved(start)) {         
           _mi_abandoned_await_readers(); // ensure no pending reads
           _mi_arena_free(start, MI_REGION_SIZE, arena_memid, (~commit == 0), tld->stats);
diff --git a/extlib/mimalloc/src/segment-cache.c b/extlib/mimalloc/src/segment-cache.c
new file mode 100644 (file)
index 0000000..aacdbc1
--- /dev/null
@@ -0,0 +1,360 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2020, Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+
+/* ----------------------------------------------------------------------------
+  Implements a cache of segments to avoid expensive OS calls and to reuse
+  the commit_mask to optimize the commit/decommit calls.
+  The full memory map of all segments is also implemented here.
+-----------------------------------------------------------------------------*/
+#include "mimalloc.h"
+#include "mimalloc-internal.h"
+#include "mimalloc-atomic.h"
+
+#include "bitmap.h"  // atomic bitmap
+
+//#define MI_CACHE_DISABLE 1    // define to completely disable the segment cache
+
+#define MI_CACHE_FIELDS     (16)
+#define MI_CACHE_MAX        (MI_BITMAP_FIELD_BITS*MI_CACHE_FIELDS)       // 1024 on 64-bit
+
+#define BITS_SET()          MI_ATOMIC_VAR_INIT(UINTPTR_MAX)
+#define MI_CACHE_BITS_SET   MI_INIT16(BITS_SET)                          // note: update if MI_CACHE_FIELDS changes
+
+typedef struct mi_cache_slot_s {
+  void*               p;
+  size_t              memid;
+  bool                is_pinned;
+  mi_commit_mask_t    commit_mask;
+  mi_commit_mask_t    decommit_mask;
+  _Atomic(mi_msecs_t) expire;
+} mi_cache_slot_t;
+
+static mi_decl_cache_align mi_cache_slot_t cache[MI_CACHE_MAX];    // = 0
+
+static mi_decl_cache_align mi_bitmap_field_t cache_available[MI_CACHE_FIELDS] = { MI_CACHE_BITS_SET };        // zero bit = available!
+static mi_decl_cache_align mi_bitmap_field_t cache_available_large[MI_CACHE_FIELDS] = { MI_CACHE_BITS_SET };
+static mi_decl_cache_align mi_bitmap_field_t cache_inuse[MI_CACHE_FIELDS];   // zero bit = free
+
+
+mi_decl_noinline void* _mi_segment_cache_pop(size_t size, mi_commit_mask_t* commit_mask, mi_commit_mask_t* decommit_mask, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
+{
+#ifdef MI_CACHE_DISABLE
+  return NULL;
+#else
+
+  // only segment blocks
+  if (size != MI_SEGMENT_SIZE) return NULL;
+
+  // numa node determines start field
+  const int numa_node = _mi_os_numa_node(tld);
+  size_t start_field = 0;
+  if (numa_node > 0) {
+    start_field = (MI_CACHE_FIELDS / _mi_os_numa_node_count())*numa_node;
+    if (start_field >= MI_CACHE_FIELDS) start_field = 0;
+  }
+
+  // find an available slot
+  mi_bitmap_index_t bitidx = 0;
+  bool claimed = false;
+  if (*large) {  // large allowed?
+    claimed = _mi_bitmap_try_find_from_claim(cache_available_large, MI_CACHE_FIELDS, start_field, 1, &bitidx);
+    if (claimed) *large = true;
+  }
+  if (!claimed) {
+    claimed = _mi_bitmap_try_find_from_claim(cache_available, MI_CACHE_FIELDS, start_field, 1, &bitidx);
+    if (claimed) *large = false;
+  }
+
+  if (!claimed) return NULL;
+
+  // found a slot
+  mi_cache_slot_t* slot = &cache[mi_bitmap_index_bit(bitidx)];
+  void* p = slot->p;
+  *memid = slot->memid;
+  *is_pinned = slot->is_pinned;
+  *is_zero = false;
+  *commit_mask = slot->commit_mask;     
+  *decommit_mask = slot->decommit_mask;
+  slot->p = NULL;
+  mi_atomic_storei64_release(&slot->expire,(mi_msecs_t)0);
+  
+  // mark the slot as free again
+  mi_assert_internal(_mi_bitmap_is_claimed(cache_inuse, MI_CACHE_FIELDS, 1, bitidx));
+  _mi_bitmap_unclaim(cache_inuse, MI_CACHE_FIELDS, 1, bitidx);
+  return p;
+#endif
+}
+
+static mi_decl_noinline void mi_commit_mask_decommit(mi_commit_mask_t* cmask, void* p, size_t total, mi_stats_t* stats)
+{
+  if (mi_commit_mask_is_empty(cmask)) {
+    // nothing
+  }
+  else if (mi_commit_mask_is_full(cmask)) {
+    _mi_os_decommit(p, total, stats);
+  }
+  else {
+    // todo: one call to decommit the whole at once?
+    mi_assert_internal((total%MI_COMMIT_MASK_BITS)==0);
+    size_t part = total/MI_COMMIT_MASK_BITS;
+    size_t idx;
+    size_t count;    
+    mi_commit_mask_foreach(cmask, idx, count) {
+      void*  start = (uint8_t*)p + (idx*part);
+      size_t size = count*part;
+      _mi_os_decommit(start, size, stats);
+    }
+    mi_commit_mask_foreach_end()
+  }
+  mi_commit_mask_create_empty(cmask);
+}
+
+#define MI_MAX_PURGE_PER_PUSH  (4)
+
+static mi_decl_noinline void mi_segment_cache_purge(bool force, mi_os_tld_t* tld)
+{
+  MI_UNUSED(tld);
+  if (!mi_option_is_enabled(mi_option_allow_decommit)) return;
+  mi_msecs_t now = _mi_clock_now();
+  size_t purged = 0;
+  const size_t max_visits = (force ? MI_CACHE_MAX /* visit all */ : MI_CACHE_FIELDS /* probe at most N (=16) slots */);
+  size_t idx              = (force ? 0 : _mi_random_shuffle((uintptr_t)now) % MI_CACHE_MAX /* random start */ );
+  for (size_t visited = 0; visited < max_visits; visited++,idx++) {  // visit N slots
+    if (idx >= MI_CACHE_MAX) idx = 0; // wrap
+    mi_cache_slot_t* slot = &cache[idx];
+    mi_msecs_t expire = mi_atomic_loadi64_relaxed(&slot->expire);
+    if (expire != 0 && (force || now >= expire)) {  // racy read
+      // seems expired, first claim it from available
+      purged++;
+      mi_bitmap_index_t bitidx = mi_bitmap_index_create_from_bit(idx);
+      if (_mi_bitmap_claim(cache_available, MI_CACHE_FIELDS, 1, bitidx, NULL)) {
+        // was available, we claimed it
+        expire = mi_atomic_loadi64_acquire(&slot->expire);
+        if (expire != 0 && (force || now >= expire)) {  // safe read
+          // still expired, decommit it
+          mi_atomic_storei64_relaxed(&slot->expire,(mi_msecs_t)0);
+          mi_assert_internal(!mi_commit_mask_is_empty(&slot->commit_mask) && _mi_bitmap_is_claimed(cache_available_large, MI_CACHE_FIELDS, 1, bitidx));
+          _mi_abandoned_await_readers();  // wait until safe to decommit
+          // decommit committed parts
+          // TODO: instead of decommit, we could also free to the OS?
+          mi_commit_mask_decommit(&slot->commit_mask, slot->p, MI_SEGMENT_SIZE, tld->stats);
+          mi_commit_mask_create_empty(&slot->decommit_mask);
+        }
+        _mi_bitmap_unclaim(cache_available, MI_CACHE_FIELDS, 1, bitidx); // make it available again for a pop
+      }
+      if (!force && purged > MI_MAX_PURGE_PER_PUSH) break;  // bound to no more than N purge tries per push
+    }
+  }
+}
+
+void _mi_segment_cache_collect(bool force, mi_os_tld_t* tld) {
+  mi_segment_cache_purge(force, tld );
+}
+
+mi_decl_noinline bool _mi_segment_cache_push(void* start, size_t size, size_t memid, const mi_commit_mask_t* commit_mask, const mi_commit_mask_t* decommit_mask, bool is_large, bool is_pinned, mi_os_tld_t* tld)
+{
+#ifdef MI_CACHE_DISABLE
+  return false;
+#else
+
+  // only for normal segment blocks
+  if (size != MI_SEGMENT_SIZE || ((uintptr_t)start % MI_SEGMENT_ALIGN) != 0) return false;
+
+  // numa node determines start field
+  int numa_node = _mi_os_numa_node(NULL);
+  size_t start_field = 0;
+  if (numa_node > 0) {
+    start_field = (MI_CACHE_FIELDS / _mi_os_numa_node_count())*numa_node;
+    if (start_field >= MI_CACHE_FIELDS) start_field = 0;
+  }
+
+  // purge expired entries
+  mi_segment_cache_purge(false /* force? */, tld);
+
+  // find an available slot
+  mi_bitmap_index_t bitidx;
+  bool claimed = _mi_bitmap_try_find_from_claim(cache_inuse, MI_CACHE_FIELDS, start_field, 1, &bitidx);
+  if (!claimed) return false;
+
+  mi_assert_internal(_mi_bitmap_is_claimed(cache_available, MI_CACHE_FIELDS, 1, bitidx));
+  mi_assert_internal(_mi_bitmap_is_claimed(cache_available_large, MI_CACHE_FIELDS, 1, bitidx));
+#if MI_DEBUG>1
+  if (is_pinned || is_large) {
+    mi_assert_internal(mi_commit_mask_is_full(commit_mask));
+  }
+#endif
+
+  // set the slot
+  mi_cache_slot_t* slot = &cache[mi_bitmap_index_bit(bitidx)];
+  slot->p = start;
+  slot->memid = memid;
+  slot->is_pinned = is_pinned;
+  mi_atomic_storei64_relaxed(&slot->expire,(mi_msecs_t)0);
+  slot->commit_mask = *commit_mask;
+  slot->decommit_mask = *decommit_mask;
+  if (!mi_commit_mask_is_empty(commit_mask) && !is_large && !is_pinned && mi_option_is_enabled(mi_option_allow_decommit)) {
+    long delay = mi_option_get(mi_option_segment_decommit_delay);
+    if (delay == 0) {
+      _mi_abandoned_await_readers(); // wait until safe to decommit
+      mi_commit_mask_decommit(&slot->commit_mask, start, MI_SEGMENT_SIZE, tld->stats);
+      mi_commit_mask_create_empty(&slot->decommit_mask);
+    }
+    else {
+      mi_atomic_storei64_release(&slot->expire, _mi_clock_now() + delay);
+    }
+  }
+
+  // make it available
+  _mi_bitmap_unclaim((is_large ? cache_available_large : cache_available), MI_CACHE_FIELDS, 1, bitidx);
+  return true;
+#endif
+}
+
+
+/* -----------------------------------------------------------
+  The following functions are to reliably find the segment or
+  block that encompasses any pointer p (or NULL if it is not
+  in any of our segments).
+  We maintain a bitmap of all memory with 1 bit per MI_SEGMENT_SIZE (64MiB)
+  set to 1 if it contains the segment meta data.
+----------------------------------------------------------- */
+
+
+#if (MI_INTPTR_SIZE==8)
+#define MI_MAX_ADDRESS    ((size_t)20 << 40)  // 20TB
+#else
+#define MI_MAX_ADDRESS    ((size_t)2 << 30)   // 2Gb
+#endif
+
+#define MI_SEGMENT_MAP_BITS  (MI_MAX_ADDRESS / MI_SEGMENT_SIZE)
+#define MI_SEGMENT_MAP_SIZE  (MI_SEGMENT_MAP_BITS / 8)
+#define MI_SEGMENT_MAP_WSIZE (MI_SEGMENT_MAP_SIZE / MI_INTPTR_SIZE)
+
+static _Atomic(uintptr_t) mi_segment_map[MI_SEGMENT_MAP_WSIZE + 1];  // 2KiB per TB with 64MiB segments
+
+static size_t mi_segment_map_index_of(const mi_segment_t* segment, size_t* bitidx) {
+  mi_assert_internal(_mi_ptr_segment(segment) == segment); // is it aligned on MI_SEGMENT_SIZE?
+  if ((uintptr_t)segment >= MI_MAX_ADDRESS) {
+    *bitidx = 0;
+    return MI_SEGMENT_MAP_WSIZE;
+  }
+  else {
+    const uintptr_t segindex = ((uintptr_t)segment) / MI_SEGMENT_SIZE;
+    *bitidx = segindex % MI_INTPTR_BITS;
+    const size_t mapindex = segindex / MI_INTPTR_BITS;
+    mi_assert_internal(mapindex < MI_SEGMENT_MAP_WSIZE);
+    return mapindex;
+  }
+}
+
+void _mi_segment_map_allocated_at(const mi_segment_t* segment) {
+  size_t bitidx;
+  size_t index = mi_segment_map_index_of(segment, &bitidx);
+  mi_assert_internal(index <= MI_SEGMENT_MAP_WSIZE);
+  if (index==MI_SEGMENT_MAP_WSIZE) return;
+  uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]);
+  uintptr_t newmask;
+  do {
+    newmask = (mask | ((uintptr_t)1 << bitidx));
+  } while (!mi_atomic_cas_weak_release(&mi_segment_map[index], &mask, newmask));
+}
+
+void _mi_segment_map_freed_at(const mi_segment_t* segment) {
+  size_t bitidx;
+  size_t index = mi_segment_map_index_of(segment, &bitidx);
+  mi_assert_internal(index <= MI_SEGMENT_MAP_WSIZE);
+  if (index == MI_SEGMENT_MAP_WSIZE) return;
+  uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]);
+  uintptr_t newmask;
+  do {
+    newmask = (mask & ~((uintptr_t)1 << bitidx));
+  } while (!mi_atomic_cas_weak_release(&mi_segment_map[index], &mask, newmask));
+}
+
+// Determine the segment belonging to a pointer or NULL if it is not in a valid segment.
+static mi_segment_t* _mi_segment_of(const void* p) {
+  mi_segment_t* segment = _mi_ptr_segment(p);
+  if (segment == NULL) return NULL; 
+  size_t bitidx;
+  size_t index = mi_segment_map_index_of(segment, &bitidx);
+  // fast path: for any pointer to valid small/medium/large object or first MI_SEGMENT_SIZE in huge
+  const uintptr_t mask = mi_atomic_load_relaxed(&mi_segment_map[index]);
+  if (mi_likely((mask & ((uintptr_t)1 << bitidx)) != 0)) {
+    return segment; // yes, allocated by us
+  }
+  if (index==MI_SEGMENT_MAP_WSIZE) return NULL;
+
+  // TODO: maintain max/min allocated range for efficiency for more efficient rejection of invalid pointers?
+
+  // search downwards for the first segment in case it is an interior pointer
+  // could be slow but searches in MI_INTPTR_SIZE * MI_SEGMENT_SIZE (512MiB) steps trough
+  // valid huge objects
+  // note: we could maintain a lowest index to speed up the path for invalid pointers?
+  size_t lobitidx;
+  size_t loindex;
+  uintptr_t lobits = mask & (((uintptr_t)1 << bitidx) - 1);
+  if (lobits != 0) {
+    loindex = index;
+    lobitidx = mi_bsr(lobits);    // lobits != 0
+  }
+  else if (index == 0) {
+    return NULL;
+  }
+  else {
+    mi_assert_internal(index > 0);
+    uintptr_t lomask = mask;
+    loindex = index;
+    do {
+      loindex--;  
+      lomask = mi_atomic_load_relaxed(&mi_segment_map[loindex]);      
+    } while (lomask != 0 && loindex > 0);
+    if (lomask == 0) return NULL;
+    lobitidx = mi_bsr(lomask);    // lomask != 0
+  }
+  mi_assert_internal(loindex < MI_SEGMENT_MAP_WSIZE);
+  // take difference as the addresses could be larger than the MAX_ADDRESS space.
+  size_t diff = (((index - loindex) * (8*MI_INTPTR_SIZE)) + bitidx - lobitidx) * MI_SEGMENT_SIZE;
+  segment = (mi_segment_t*)((uint8_t*)segment - diff);
+
+  if (segment == NULL) return NULL;
+  mi_assert_internal((void*)segment < p);
+  bool cookie_ok = (_mi_ptr_cookie(segment) == segment->cookie);
+  mi_assert_internal(cookie_ok);
+  if (mi_unlikely(!cookie_ok)) return NULL;
+  if (((uint8_t*)segment + mi_segment_size(segment)) <= (uint8_t*)p) return NULL; // outside the range
+  mi_assert_internal(p >= (void*)segment && (uint8_t*)p < (uint8_t*)segment + mi_segment_size(segment));
+  return segment;
+}
+
+// Is this a valid pointer in our heap?
+static bool  mi_is_valid_pointer(const void* p) {
+  return (_mi_segment_of(p) != NULL);
+}
+
+mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept {
+  return mi_is_valid_pointer(p);
+}
+
+/*
+// Return the full segment range belonging to a pointer
+static void* mi_segment_range_of(const void* p, size_t* size) {
+  mi_segment_t* segment = _mi_segment_of(p);
+  if (segment == NULL) {
+    if (size != NULL) *size = 0;
+    return NULL;
+  }
+  else {
+    if (size != NULL) *size = segment->segment_size;
+    return segment;
+  }
+  mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld));
+  mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size);
+  mi_reset_delayed(tld);
+  mi_assert_internal(page == NULL || mi_page_not_in_queue(page, tld));
+  return page;
+}
+*/
index 8a5ba8c0a3be6662888064d0c42c43bfdc96266d..800d4fc31f3481f14d651331321a0d68cadccd92 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -13,429 +13,343 @@ terms of the MIT license. A copy of the license can be found in the file
 
 #define MI_PAGE_HUGE_ALIGN  (256*1024)
 
-static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size);
+static void mi_segment_delayed_decommit(mi_segment_t* segment, bool force, mi_stats_t* stats);
 
-/* --------------------------------------------------------------------------------
-  Segment allocation
-  We allocate pages inside bigger "segments" (4mb on 64-bit). This is to avoid
-  splitting VMA's on Linux and reduce fragmentation on other OS's.
-  Each thread owns its own segments.
-
-  Currently we have:
-  - small pages (64kb), 64 in one segment
-  - medium pages (512kb), 8 in one segment
-  - large pages (4mb), 1 in one segment
-  - huge blocks > MI_LARGE_OBJ_SIZE_MAX become large segment with 1 page
 
-  In any case the memory for a segment is virtual and usually committed on demand.
-  (i.e. we are careful to not touch the memory until we actually allocate a block there)
-
-  If a  thread ends, it "abandons" pages with used blocks
-  and there is an abandoned segment list whose segments can
-  be reclaimed by still running threads, much like work-stealing.
--------------------------------------------------------------------------------- */
-
-
-/* -----------------------------------------------------------
-  Queue of segments containing free pages
------------------------------------------------------------ */
+// -------------------------------------------------------------------
+// commit mask 
+// -------------------------------------------------------------------
 
-#if (MI_DEBUG>=3)
-static bool mi_segment_queue_contains(const mi_segment_queue_t* queue, const mi_segment_t* segment) {
-  mi_assert_internal(segment != NULL);
-  mi_segment_t* list = queue->first;
-  while (list != NULL) {
-    if (list == segment) break;
-    mi_assert_internal(list->next==NULL || list->next->prev == list);
-    mi_assert_internal(list->prev==NULL || list->prev->next == list);
-    list = list->next;
+static bool mi_commit_mask_all_set(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    if ((commit->mask[i] & cm->mask[i]) != cm->mask[i]) return false;
   }
-  return (list == segment);
-}
-#endif
-
-static bool mi_segment_queue_is_empty(const mi_segment_queue_t* queue) {
-  return (queue->first == NULL);
-}
-
-static void mi_segment_queue_remove(mi_segment_queue_t* queue, mi_segment_t* segment) {
-  mi_assert_expensive(mi_segment_queue_contains(queue, segment));
-  if (segment->prev != NULL) segment->prev->next = segment->next;
-  if (segment->next != NULL) segment->next->prev = segment->prev;
-  if (segment == queue->first) queue->first = segment->next;
-  if (segment == queue->last)  queue->last = segment->prev;
-  segment->next = NULL;
-  segment->prev = NULL;
+  return true;
 }
 
-static void mi_segment_enqueue(mi_segment_queue_t* queue, mi_segment_t* segment) {
-  mi_assert_expensive(!mi_segment_queue_contains(queue, segment));
-  segment->next = NULL;
-  segment->prev = queue->last;
-  if (queue->last != NULL) {
-    mi_assert_internal(queue->last->next == NULL);
-    queue->last->next = segment;
-    queue->last = segment;
-  }
-  else {
-    queue->last = queue->first = segment;
+static bool mi_commit_mask_any_set(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    if ((commit->mask[i] & cm->mask[i]) != 0) return true;
   }
+  return false;
 }
 
-static mi_segment_queue_t* mi_segment_free_queue_of_kind(mi_page_kind_t kind, mi_segments_tld_t* tld) {
-  if (kind == MI_PAGE_SMALL) return &tld->small_free;
-  else if (kind == MI_PAGE_MEDIUM) return &tld->medium_free;
-  else return NULL;
-}
-
-static mi_segment_queue_t* mi_segment_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) {
-  return mi_segment_free_queue_of_kind(segment->page_kind, tld);
-}
-
-// remove from free queue if it is in one
-static void mi_segment_remove_from_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld); // may be NULL
-  bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment));
-  if (in_queue) {
-    mi_segment_queue_remove(queue, segment);
+static void mi_commit_mask_create_intersect(const mi_commit_mask_t* commit, const mi_commit_mask_t* cm, mi_commit_mask_t* res) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    res->mask[i] = (commit->mask[i] & cm->mask[i]);
   }
 }
 
-static void mi_segment_insert_in_free_queue(mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_segment_enqueue(mi_segment_free_queue(segment, tld), segment);
+static void mi_commit_mask_clear(mi_commit_mask_t* res, const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    res->mask[i] &= ~(cm->mask[i]);
+  }
 }
 
-
-/* -----------------------------------------------------------
- Invariant checking
------------------------------------------------------------ */
-
-#if (MI_DEBUG>=2)
-static bool mi_segment_is_in_free_queue(const mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_segment_queue_t* queue = mi_segment_free_queue(segment, tld);
-  bool in_queue = (queue!=NULL && (segment->next != NULL || segment->prev != NULL || queue->first == segment));
-  if (in_queue) {
-    mi_assert_expensive(mi_segment_queue_contains(queue, segment));
+static void mi_commit_mask_set(mi_commit_mask_t* res, const mi_commit_mask_t* cm) {
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    res->mask[i] |= cm->mask[i];
   }
-  return in_queue;
 }
-#endif
 
-static size_t mi_segment_page_size(const mi_segment_t* segment) {
-  if (segment->capacity > 1) {
-    mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM);
-    return ((size_t)1 << segment->page_shift);
+static void mi_commit_mask_create(size_t bitidx, size_t bitcount, mi_commit_mask_t* cm) {
+  mi_assert_internal(bitidx < MI_COMMIT_MASK_BITS);
+  mi_assert_internal((bitidx + bitcount) <= MI_COMMIT_MASK_BITS);
+  if (bitcount == MI_COMMIT_MASK_BITS) {
+    mi_assert_internal(bitidx==0);
+    mi_commit_mask_create_full(cm);
   }
-  else {
-    mi_assert_internal(segment->page_kind >= MI_PAGE_LARGE);
-    return segment->segment_size;
+  else if (bitcount == 0) {
+    mi_commit_mask_create_empty(cm);
   }
-}
-
-
-#if (MI_DEBUG>=2)
-static bool mi_pages_reset_contains(const mi_page_t* page, mi_segments_tld_t* tld) {
-  mi_page_t* p = tld->pages_reset.first;
-  while (p != NULL) {
-    if (p == page) return true;
-    p = p->next;
+  else {
+    mi_commit_mask_create_empty(cm);
+    size_t i = bitidx / MI_COMMIT_MASK_FIELD_BITS;
+    size_t ofs = bitidx % MI_COMMIT_MASK_FIELD_BITS;
+    while (bitcount > 0) {
+      mi_assert_internal(i < MI_COMMIT_MASK_FIELD_COUNT);
+      size_t avail = MI_COMMIT_MASK_FIELD_BITS - ofs;
+      size_t count = (bitcount > avail ? avail : bitcount);
+      size_t mask = (count >= MI_COMMIT_MASK_FIELD_BITS ? ~((size_t)0) : (((size_t)1 << count) - 1) << ofs);
+      cm->mask[i] = mask;
+      bitcount -= count;
+      ofs = 0;
+      i++;
+    }
   }
-  return false;
 }
-#endif
 
-#if (MI_DEBUG>=3)
-static bool mi_segment_is_valid(const mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_assert_internal(segment != NULL);
-  mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie);
-  mi_assert_internal(segment->used <= segment->capacity);
-  mi_assert_internal(segment->abandoned <= segment->used);
-  size_t nfree = 0;
-  for (size_t i = 0; i < segment->capacity; i++) {
-    const mi_page_t* const page = &segment->pages[i];
-    if (!page->segment_in_use) {
-      nfree++;
+size_t _mi_commit_mask_committed_size(const mi_commit_mask_t* cm, size_t total) {
+  mi_assert_internal((total%MI_COMMIT_MASK_BITS)==0);
+  size_t count = 0;
+  for (size_t i = 0; i < MI_COMMIT_MASK_FIELD_COUNT; i++) {
+    size_t mask = cm->mask[i];
+    if (~mask == 0) {
+      count += MI_COMMIT_MASK_FIELD_BITS;
     }
-    if (page->segment_in_use || page->is_reset) {
-      mi_assert_expensive(!mi_pages_reset_contains(page, tld));
+    else {
+      for (; mask != 0; mask >>= 1) {  // todo: use popcount
+        if ((mask&1)!=0) count++;
+      }
     }
   }
-  mi_assert_internal(nfree + segment->used == segment->capacity);
-  // mi_assert_internal(segment->thread_id == _mi_thread_id() || (segment->thread_id==0)); // or 0
-  mi_assert_internal(segment->page_kind == MI_PAGE_HUGE ||
-                     (mi_segment_page_size(segment) * segment->capacity == segment->segment_size));
-  return true;
+  // we use total since for huge segments each commit bit may represent a larger size
+  return ((total / MI_COMMIT_MASK_BITS) * count);
 }
-#endif
 
-static bool mi_page_not_in_queue(const mi_page_t* page, mi_segments_tld_t* tld) {
-  mi_assert_internal(page != NULL);
-  if (page->next != NULL || page->prev != NULL) {
-    mi_assert_internal(mi_pages_reset_contains(page, tld));
-    return false;
+
+size_t _mi_commit_mask_next_run(const mi_commit_mask_t* cm, size_t* idx) {
+  size_t i = (*idx) / MI_COMMIT_MASK_FIELD_BITS;
+  size_t ofs = (*idx) % MI_COMMIT_MASK_FIELD_BITS;
+  size_t mask = 0;
+  // find first ones
+  while (i < MI_COMMIT_MASK_FIELD_COUNT) {
+    mask = cm->mask[i];
+    mask >>= ofs;
+    if (mask != 0) {
+      while ((mask&1) == 0) {
+        mask >>= 1;
+        ofs++;
+      }
+      break;
+    }
+    i++;
+    ofs = 0;
+  }
+  if (i >= MI_COMMIT_MASK_FIELD_COUNT) {
+    // not found
+    *idx = MI_COMMIT_MASK_BITS;
+    return 0;
   }
   else {
-    // both next and prev are NULL, check for singleton list
-    return (tld->pages_reset.first != page && tld->pages_reset.last != page);
+    // found, count ones
+    size_t count = 0;
+    *idx = (i*MI_COMMIT_MASK_FIELD_BITS) + ofs;
+    do {
+      mi_assert_internal(ofs < MI_COMMIT_MASK_FIELD_BITS && (mask&1) == 1);
+      do {
+        count++;
+        mask >>= 1;
+      } while ((mask&1) == 1);
+      if ((((*idx + count) % MI_COMMIT_MASK_FIELD_BITS) == 0)) {
+        i++;
+        if (i >= MI_COMMIT_MASK_FIELD_COUNT) break;
+        mask = cm->mask[i];
+        ofs = 0;
+      }
+    } while ((mask&1) == 1);
+    mi_assert_internal(count > 0);
+    return count;
   }
 }
 
 
+/* --------------------------------------------------------------------------------
+  Segment allocation
+
+  If a  thread ends, it "abandons" pages with used blocks
+  and there is an abandoned segment list whose segments can
+  be reclaimed by still running threads, much like work-stealing.
+-------------------------------------------------------------------------------- */
+
+
 /* -----------------------------------------------------------
-  Guard pages
+   Slices
 ----------------------------------------------------------- */
 
-static void mi_segment_protect_range(void* p, size_t size, bool protect) {
-  if (protect) {
-    _mi_mem_protect(p, size);
-  }
-  else {
-    _mi_mem_unprotect(p, size);
-  }
-}
-
-static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t* tld) {
-  // add/remove guard pages
-  if (MI_SECURE != 0) {
-    // in secure mode, we set up a protected page in between the segment info and the page data
-    const size_t os_page_size = _mi_os_page_size();
-    mi_assert_internal((segment->segment_info_size - os_page_size) >= (sizeof(mi_segment_t) + ((segment->capacity - 1) * sizeof(mi_page_t))));
-    mi_assert_internal(((uintptr_t)segment + segment->segment_info_size) % os_page_size == 0);
-    mi_segment_protect_range((uint8_t*)segment + segment->segment_info_size - os_page_size, os_page_size, protect);
-    if (MI_SECURE <= 1 || segment->capacity == 1) {
-      // and protect the last (or only) page too
-      mi_assert_internal(MI_SECURE <= 1 || segment->page_kind >= MI_PAGE_LARGE);
-      uint8_t* start = (uint8_t*)segment + segment->segment_size - os_page_size;
-      if (protect && !segment->mem_is_committed) {
-        // ensure secure page is committed
-        _mi_mem_commit(start, os_page_size, NULL, tld);
-      }
-      mi_segment_protect_range(start, os_page_size, protect);
-    }
-    else {
-      // or protect every page
-      const size_t page_size = mi_segment_page_size(segment);
-      for (size_t i = 0; i < segment->capacity; i++) {
-        if (segment->pages[i].is_committed) {
-          mi_segment_protect_range((uint8_t*)segment + (i+1)*page_size - os_page_size, os_page_size, protect);
-        }
-      }
-    }
-  }
+
+static const mi_slice_t* mi_segment_slices_end(const mi_segment_t* segment) {
+  return &segment->slices[segment->slice_entries];
 }
 
+static uint8_t* mi_slice_start(const mi_slice_t* slice) {
+  mi_segment_t* segment = _mi_ptr_segment(slice);
+  mi_assert_internal(slice >= segment->slices && slice < mi_segment_slices_end(segment));
+  return ((uint8_t*)segment + ((slice - segment->slices)*MI_SEGMENT_SLICE_SIZE));
+}
+
+
 /* -----------------------------------------------------------
-  Page reset
+   Bins
 ----------------------------------------------------------- */
+// Use bit scan forward to quickly find the first zero bit if it is available
+
+static inline size_t mi_slice_bin8(size_t slice_count) {
+  if (slice_count<=1) return slice_count;
+  mi_assert_internal(slice_count <= MI_SLICES_PER_SEGMENT);
+  slice_count--;
+  size_t s = mi_bsr(slice_count);  // slice_count > 1
+  if (s <= 2) return slice_count + 1;
+  size_t bin = ((s << 2) | ((slice_count >> (s - 2))&0x03)) - 4;
+  return bin;
+}
 
-static void mi_page_reset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) {
-  mi_assert_internal(page->is_committed);
-  if (!mi_option_is_enabled(mi_option_page_reset)) return;
-  if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return;
-  size_t psize;
-  void* start = mi_segment_raw_page_start(segment, page, &psize);
-  page->is_reset = true;
-  mi_assert_internal(size <= psize);
-  size_t reset_size = ((size == 0 || size > psize) ? psize : size);
-  if (reset_size > 0) _mi_mem_reset(start, reset_size, tld->os);
+static inline size_t mi_slice_bin(size_t slice_count) {
+  mi_assert_internal(slice_count*MI_SEGMENT_SLICE_SIZE <= MI_SEGMENT_SIZE);
+  mi_assert_internal(mi_slice_bin8(MI_SLICES_PER_SEGMENT) <= MI_SEGMENT_BIN_MAX);
+  size_t bin = mi_slice_bin8(slice_count);
+  mi_assert_internal(bin <= MI_SEGMENT_BIN_MAX);
+  return bin;
 }
 
-static bool mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld)
-{
-  mi_assert_internal(page->is_reset);
-  mi_assert_internal(page->is_committed);
-  mi_assert_internal(!segment->mem_is_fixed);
-  if (segment->mem_is_fixed || !page->is_committed || !page->is_reset) return true;
-  page->is_reset = false;
-  size_t psize;
-  uint8_t* start = mi_segment_raw_page_start(segment, page, &psize);
-  size_t unreset_size = (size == 0 || size > psize ? psize : size);
-  bool is_zero = false;
-  bool ok = true;
-  if (unreset_size > 0) {
-    ok = _mi_mem_unreset(start, unreset_size, &is_zero, tld->os);
-  }
-  if (is_zero) page->is_zero_init = true;
-  return ok;
+static inline size_t mi_slice_index(const mi_slice_t* slice) {
+  mi_segment_t* segment = _mi_ptr_segment(slice);
+  ptrdiff_t index = slice - segment->slices;
+  mi_assert_internal(index >= 0 && index < (ptrdiff_t)segment->slice_entries);
+  return index;
 }
 
 
 /* -----------------------------------------------------------
-  The free page queue
+   Slice span queues
 ----------------------------------------------------------- */
 
-// we re-use the `used` field for the expiration counter. Since this is a
-// a 32-bit field while the clock is always 64-bit we need to guard
-// against overflow, we use substraction to check for expiry which work
-// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days)
-static void mi_page_reset_set_expire(mi_page_t* page) {
-  uint32_t expire = (uint32_t)_mi_clock_now() + mi_option_get(mi_option_reset_delay);
-  page->used = expire;
+static void mi_span_queue_push(mi_span_queue_t* sq, mi_slice_t* slice) {
+  // todo: or push to the end?
+  mi_assert_internal(slice->prev == NULL && slice->next==NULL);
+  slice->prev = NULL; // paranoia
+  slice->next = sq->first;
+  sq->first = slice;
+  if (slice->next != NULL) slice->next->prev = slice;
+                     else sq->last = slice;
+  slice->xblock_size = 0; // free
 }
 
-static bool mi_page_reset_is_expired(mi_page_t* page, mi_msecs_t now) {
-  int32_t expire = (int32_t)(page->used);
-  return (((int32_t)now - expire) >= 0);
+static mi_span_queue_t* mi_span_queue_for(size_t slice_count, mi_segments_tld_t* tld) {
+  size_t bin = mi_slice_bin(slice_count);
+  mi_span_queue_t* sq = &tld->spans[bin];
+  mi_assert_internal(sq->slice_count >= slice_count);
+  return sq;
 }
 
-static void mi_pages_reset_add(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) {
-  mi_assert_internal(!page->segment_in_use || !page->is_committed);
-  mi_assert_internal(mi_page_not_in_queue(page,tld));
-  mi_assert_expensive(!mi_pages_reset_contains(page, tld));
-  mi_assert_internal(_mi_page_segment(page)==segment);
-  if (!mi_option_is_enabled(mi_option_page_reset)) return;
-  if (segment->mem_is_fixed || page->segment_in_use || !page->is_committed || page->is_reset) return;
+static void mi_span_queue_delete(mi_span_queue_t* sq, mi_slice_t* slice) {
+  mi_assert_internal(slice->xblock_size==0 && slice->slice_count>0 && slice->slice_offset==0);
+  // should work too if the queue does not contain slice (which can happen during reclaim)
+  if (slice->prev != NULL) slice->prev->next = slice->next;
+  if (slice == sq->first) sq->first = slice->next;
+  if (slice->next != NULL) slice->next->prev = slice->prev;
+  if (slice == sq->last) sq->last = slice->prev;
+  slice->prev = NULL;
+  slice->next = NULL;
+  slice->xblock_size = 1; // no more free
+}
 
-  if (mi_option_get(mi_option_reset_delay) == 0) {
-    // reset immediately?
-    mi_page_reset(segment, page, 0, tld);
-  }
-  else {
-    // otherwise push on the delayed page reset queue
-    mi_page_queue_t* pq = &tld->pages_reset;
-    // push on top
-    mi_page_reset_set_expire(page);
-    page->next = pq->first;
-    page->prev = NULL;
-    if (pq->first == NULL) {
-      mi_assert_internal(pq->last == NULL);
-      pq->first = pq->last = page;
-    }
-    else {
-      pq->first->prev = page;
-      pq->first = page;
-    }
-  }
+
+/* -----------------------------------------------------------
+ Invariant checking
+----------------------------------------------------------- */
+
+static bool mi_slice_is_used(const mi_slice_t* slice) {
+  return (slice->xblock_size > 0);
 }
 
-static void mi_pages_reset_remove(mi_page_t* page, mi_segments_tld_t* tld) {
-  if (mi_page_not_in_queue(page,tld)) return;
 
-  mi_page_queue_t* pq = &tld->pages_reset;
-  mi_assert_internal(pq!=NULL);
-  mi_assert_internal(!page->segment_in_use);
-  mi_assert_internal(mi_pages_reset_contains(page, tld));
-  if (page->prev != NULL) page->prev->next = page->next;
-  if (page->next != NULL) page->next->prev = page->prev;
-  if (page == pq->last)  pq->last = page->prev;
-  if (page == pq->first) pq->first = page->next;
-  page->next = page->prev = NULL;
-  page->used = 0;
+#if (MI_DEBUG>=3)
+static bool mi_span_queue_contains(mi_span_queue_t* sq, mi_slice_t* slice) {
+  for (mi_slice_t* s = sq->first; s != NULL; s = s->next) {
+    if (s==slice) return true;
+  }
+  return false;
 }
 
-static void mi_pages_reset_remove_all_in_segment(mi_segment_t* segment, bool force_reset, mi_segments_tld_t* tld) {
-  if (segment->mem_is_fixed) return; // never reset in huge OS pages
-  for (size_t i = 0; i < segment->capacity; i++) {
-    mi_page_t* page = &segment->pages[i];
-    if (!page->segment_in_use && page->is_committed && !page->is_reset) {
-      mi_pages_reset_remove(page, tld);
-      if (force_reset) {
-        mi_page_reset(segment, page, 0, tld);
+static bool mi_segment_is_valid(mi_segment_t* segment, mi_segments_tld_t* tld) {
+  mi_assert_internal(segment != NULL);
+  mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie);
+  mi_assert_internal(segment->abandoned <= segment->used);
+  mi_assert_internal(segment->thread_id == 0 || segment->thread_id == _mi_thread_id());
+  mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask)); // can only decommit committed blocks
+  //mi_assert_internal(segment->segment_info_size % MI_SEGMENT_SLICE_SIZE == 0);
+  mi_slice_t* slice = &segment->slices[0];
+  const mi_slice_t* end = mi_segment_slices_end(segment);
+  size_t used_count = 0;
+  mi_span_queue_t* sq;
+  while(slice < end) {
+    mi_assert_internal(slice->slice_count > 0);
+    mi_assert_internal(slice->slice_offset == 0);
+    size_t index = mi_slice_index(slice);
+    size_t maxindex = (index + slice->slice_count >= segment->slice_entries ? segment->slice_entries : index + slice->slice_count) - 1;
+    if (mi_slice_is_used(slice)) { // a page in use, we need at least MAX_SLICE_OFFSET valid back offsets
+      used_count++;
+      for (size_t i = 0; i <= MI_MAX_SLICE_OFFSET && index + i <= maxindex; i++) {
+        mi_assert_internal(segment->slices[index + i].slice_offset == i*sizeof(mi_slice_t));
+        mi_assert_internal(i==0 || segment->slices[index + i].slice_count == 0);
+        mi_assert_internal(i==0 || segment->slices[index + i].xblock_size == 1);
+      }
+      // and the last entry as well (for coalescing)
+      const mi_slice_t* last = slice + slice->slice_count - 1;
+      if (last > slice && last < mi_segment_slices_end(segment)) {
+        mi_assert_internal(last->slice_offset == (slice->slice_count-1)*sizeof(mi_slice_t));
+        mi_assert_internal(last->slice_count == 0);
+        mi_assert_internal(last->xblock_size == 1);
       }
     }
-    else {
-      mi_assert_internal(mi_page_not_in_queue(page,tld));
+    else {  // free range of slices; only last slice needs a valid back offset
+      mi_slice_t* last = &segment->slices[maxindex];
+      if (segment->kind != MI_SEGMENT_HUGE || slice->slice_count <= (segment->slice_entries - segment->segment_info_slices)) {
+        mi_assert_internal((uint8_t*)slice == (uint8_t*)last - last->slice_offset);
+      }
+      mi_assert_internal(slice == last || last->slice_count == 0 );
+      mi_assert_internal(last->xblock_size == 0 || (segment->kind==MI_SEGMENT_HUGE && last->xblock_size==1));
+      if (segment->kind != MI_SEGMENT_HUGE && segment->thread_id != 0) { // segment is not huge or abandoned
+        sq = mi_span_queue_for(slice->slice_count,tld);
+        mi_assert_internal(mi_span_queue_contains(sq,slice));
+      }
     }
+    slice = &segment->slices[maxindex+1];
   }
+  mi_assert_internal(slice == end);
+  mi_assert_internal(used_count == segment->used + 1);
+  return true;
 }
-
-static void mi_reset_delayed(mi_segments_tld_t* tld) {
-  if (!mi_option_is_enabled(mi_option_page_reset)) return;
-  mi_msecs_t now = _mi_clock_now();
-  mi_page_queue_t* pq = &tld->pages_reset;
-  // from oldest up to the first that has not expired yet
-  mi_page_t* page = pq->last;
-  while (page != NULL && mi_page_reset_is_expired(page,now)) {
-    mi_page_t* const prev = page->prev; // save previous field
-    mi_page_reset(_mi_page_segment(page), page, 0, tld);
-    page->used = 0;
-    page->prev = page->next = NULL;
-    page = prev;
-  }
-  // discard the reset pages from the queue
-  pq->last = page;
-  if (page != NULL){
-    page->next = NULL;
-  }
-  else {
-    pq->first = NULL;
-  }
-}
-
+#endif
 
 /* -----------------------------------------------------------
  Segment size calculations
 ----------------------------------------------------------- */
 
-// Raw start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set)
-// The raw start is not taking aligned block allocation into consideration.
-static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) {
-  size_t   psize = (segment->page_kind == MI_PAGE_HUGE ? segment->segment_size : (size_t)1 << segment->page_shift);
-  uint8_t* p = (uint8_t*)segment + page->segment_idx * psize;
-
-  if (page->segment_idx == 0) {
-    // the first page starts after the segment info (and possible guard page)
-    p += segment->segment_info_size;
-    psize -= segment->segment_info_size;
-  }
-
-  if (MI_SECURE > 1 || (MI_SECURE == 1 && page->segment_idx == segment->capacity - 1)) {
-    // secure == 1: the last page has an os guard page at the end
-    // secure >  1: every page has an os guard page
-    psize -= _mi_os_page_size();
-  }
-
-  if (page_size != NULL) *page_size = psize;
-  mi_assert_internal(page->xblock_size == 0 || _mi_ptr_page(p) == page);
-  mi_assert_internal(_mi_ptr_segment(p) == segment);
-  return p;
+static size_t mi_segment_info_size(mi_segment_t* segment) {
+  return segment->segment_info_slices * MI_SEGMENT_SLICE_SIZE;
 }
 
-// Start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set)
-uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size)
+static uint8_t* _mi_segment_page_start_from_slice(const mi_segment_t* segment, const mi_slice_t* slice, size_t xblock_size, size_t* page_size)
 {
-  size_t   psize;
-  uint8_t* p = mi_segment_raw_page_start(segment, page, &psize);
-  if (pre_size != NULL) *pre_size = 0;
-  if (page->segment_idx == 0 && block_size > 0 && segment->page_kind <= MI_PAGE_MEDIUM) {
-    // for small and medium objects, ensure the page start is aligned with the block size (PR#66 by kickunderscore)
-    size_t adjust = block_size - ((uintptr_t)p % block_size);
-    if (adjust < block_size) {
-      p += adjust;
-      psize -= adjust;
-      if (pre_size != NULL) *pre_size = adjust;
-    }
-    mi_assert_internal((uintptr_t)p % block_size == 0);
-  }
+  ptrdiff_t idx = slice - segment->slices;
+  size_t psize = (size_t)slice->slice_count * MI_SEGMENT_SLICE_SIZE;
+  // make the start not OS page aligned for smaller blocks to avoid page/cache effects
+  size_t start_offset = (xblock_size >= MI_INTPTR_SIZE && xblock_size <= 1024 ? MI_MAX_ALIGN_GUARANTEE : 0); 
+  if (page_size != NULL) { *page_size = psize - start_offset; }
+  return (uint8_t*)segment + ((idx*MI_SEGMENT_SLICE_SIZE) + start_offset);
+}
 
-  if (page_size != NULL) *page_size = psize;
-  mi_assert_internal(page->xblock_size==0 || _mi_ptr_page(p) == page);
+// Start of the page available memory; can be used on uninitialized pages
+uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size)
+{
+  const mi_slice_t* slice = mi_page_to_slice((mi_page_t*)page);
+  uint8_t* p = _mi_segment_page_start_from_slice(segment, slice, page->xblock_size, page_size);  
+  mi_assert_internal(page->xblock_size > 0 || _mi_ptr_page(p) == page);
   mi_assert_internal(_mi_ptr_segment(p) == segment);
   return p;
 }
 
-static size_t mi_segment_size(size_t capacity, size_t required, size_t* pre_size, size_t* info_size)
-{
-  const size_t minsize   = sizeof(mi_segment_t) + ((capacity - 1) * sizeof(mi_page_t)) + 16 /* padding */;
+
+static size_t mi_segment_calculate_slices(size_t required, size_t* pre_size, size_t* info_slices) {
+  size_t page_size = _mi_os_page_size();
+  size_t isize     = _mi_align_up(sizeof(mi_segment_t), page_size);
   size_t guardsize = 0;
-  size_t isize     = 0;
 
-  if (MI_SECURE == 0) {
-    // normally no guard pages
-    isize = _mi_align_up(minsize, 16 * MI_MAX_ALIGN_SIZE);
-  }
-  else {
+  if (MI_SECURE>0) {
     // in secure mode, we set up a protected page in between the segment info
     // and the page data (and one at the end of the segment)
-    const size_t page_size = _mi_os_page_size();
-    isize = _mi_align_up(minsize, page_size);
-    guardsize = page_size;
-    required = _mi_align_up(required, page_size);
+    guardsize =  page_size;
+    required  = _mi_align_up(required, page_size);
   }
 
-  if (info_size != NULL) *info_size = isize;
-  if (pre_size != NULL)  *pre_size  = isize + guardsize;
-  return (required==0 ? MI_SEGMENT_SIZE : _mi_align_up( required + isize + 2*guardsize, MI_PAGE_HUGE_ALIGN) );
+  if (pre_size != NULL) *pre_size = isize;
+  isize = _mi_align_up(isize + guardsize, MI_SEGMENT_SLICE_SIZE);
+  if (info_slices != NULL) *info_slices = isize / MI_SEGMENT_SLICE_SIZE;
+  size_t segment_size = (required==0 ? MI_SEGMENT_SIZE : _mi_align_up( required + isize + guardsize, MI_SEGMENT_SLICE_SIZE) );  
+  mi_assert_internal(segment_size % MI_SEGMENT_SLICE_SIZE == 0);
+  return (segment_size / MI_SEGMENT_SLICE_SIZE);
 }
 
 
@@ -454,92 +368,387 @@ static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) {
   if (tld->current_size > tld->peak_size) tld->peak_size = tld->current_size;
 }
 
-static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_segments_tld_t* tld) {
+static void mi_segment_os_free(mi_segment_t* segment, mi_segments_tld_t* tld) {
   segment->thread_id = 0;
-  mi_segments_track_size(-((long)segment_size),tld);
-  if (MI_SECURE != 0) {
-    mi_assert_internal(!segment->mem_is_fixed);
-    mi_segment_protect(segment, false, tld->os); // ensure no more guard pages are set
+  _mi_segment_map_freed_at(segment);
+  mi_segments_track_size(-((long)mi_segment_size(segment)),tld);
+  if (MI_SECURE>0) {
+    // _mi_os_unprotect(segment, mi_segment_size(segment)); // ensure no more guard pages are set
+    // unprotect the guard pages; we cannot just unprotect the whole segment size as part may be decommitted
+    size_t os_pagesize = _mi_os_page_size();
+    _mi_os_unprotect((uint8_t*)segment + mi_segment_info_size(segment) - os_pagesize, os_pagesize);
+    uint8_t* end = (uint8_t*)segment + mi_segment_size(segment) - os_pagesize;
+    _mi_os_unprotect(end, os_pagesize);
+  }
+
+  // purge delayed decommits now? (no, leave it to the cache)
+  // mi_segment_delayed_decommit(segment,true,tld->stats);
+  
+  // _mi_os_free(segment, mi_segment_size(segment), /*segment->memid,*/ tld->stats);
+  const size_t size = mi_segment_size(segment);
+  if (size != MI_SEGMENT_SIZE || !_mi_segment_cache_push(segment, size, segment->memid, &segment->commit_mask, &segment->decommit_mask, segment->mem_is_large, segment->mem_is_pinned, tld->os)) {
+    const size_t csize = _mi_commit_mask_committed_size(&segment->commit_mask, size);
+    if (csize > 0 && !segment->mem_is_pinned) _mi_stat_decrease(&_mi_stats_main.committed, csize);
+    _mi_abandoned_await_readers();  // wait until safe to free
+    _mi_arena_free(segment, mi_segment_size(segment), segment->memid, segment->mem_is_pinned /* pretend not committed to not double count decommits */, tld->os);
   }
+}
 
-  bool any_reset = false;
-  bool fully_committed = true;
-  for (size_t i = 0; i < segment->capacity; i++) {
-    mi_page_t* page = &segment->pages[i];
-    if (!page->is_committed) { fully_committed = false; }
-    if (page->is_reset)      { any_reset = true; }
+// called by threads that are terminating 
+void _mi_segment_thread_collect(mi_segments_tld_t* tld) {
+  MI_UNUSED(tld);
+  // nothing to do
+}
+
+
+/* -----------------------------------------------------------
+   Span management
+----------------------------------------------------------- */
+
+static void mi_segment_commit_mask(mi_segment_t* segment, bool conservative, uint8_t* p, size_t size, uint8_t** start_p, size_t* full_size, mi_commit_mask_t* cm) {
+  mi_assert_internal(_mi_ptr_segment(p) == segment);
+  mi_assert_internal(segment->kind != MI_SEGMENT_HUGE);
+  mi_commit_mask_create_empty(cm);
+  if (size == 0 || size > MI_SEGMENT_SIZE || segment->kind == MI_SEGMENT_HUGE) return;
+  const size_t segstart = mi_segment_info_size(segment);
+  const size_t segsize = mi_segment_size(segment);
+  if (p >= (uint8_t*)segment + segsize) return;
+
+  size_t pstart = (p - (uint8_t*)segment);
+  mi_assert_internal(pstart + size <= segsize);
+
+  size_t start;
+  size_t end;
+  if (conservative) {
+    // decommit conservative
+    start = _mi_align_up(pstart, MI_COMMIT_SIZE);
+    end   = _mi_align_down(pstart + size, MI_COMMIT_SIZE);
+    mi_assert_internal(start >= segstart);
+    mi_assert_internal(end <= segsize);
+  }
+  else {
+    // commit liberal
+    start = _mi_align_down(pstart, MI_MINIMAL_COMMIT_SIZE);
+    end   = _mi_align_up(pstart + size, MI_MINIMAL_COMMIT_SIZE);
   }
-  if (any_reset && mi_option_is_enabled(mi_option_reset_decommits)) {
-    fully_committed = false;
+  if (pstart >= segstart && start < segstart) {  // note: the mask is also calculated for an initial commit of the info area
+    start = segstart;
   }
+  if (end > segsize) {
+    end = segsize;
+  }
+
+  mi_assert_internal(start <= pstart && (pstart + size) <= end);
+  mi_assert_internal(start % MI_COMMIT_SIZE==0 && end % MI_COMMIT_SIZE == 0);
+  *start_p   = (uint8_t*)segment + start;
+  *full_size = (end > start ? end - start : 0);
+  if (*full_size == 0) return;
+
+  size_t bitidx = start / MI_COMMIT_SIZE;
+  mi_assert_internal(bitidx < MI_COMMIT_MASK_BITS);
   
-  _mi_mem_free(segment, segment_size, segment->memid, fully_committed, any_reset, tld->os);
+  size_t bitcount = *full_size / MI_COMMIT_SIZE; // can be 0
+  if (bitidx + bitcount > MI_COMMIT_MASK_BITS) {
+    _mi_warning_message("commit mask overflow: idx=%zu count=%zu start=%zx end=%zx p=0x%p size=%zu fullsize=%zu\n", bitidx, bitcount, start, end, p, size, *full_size);
+  }
+  mi_assert_internal((bitidx + bitcount) <= MI_COMMIT_MASK_BITS);
+  mi_commit_mask_create(bitidx, bitcount, cm);
 }
 
 
-// The thread local segment cache is limited to be at most 1/8 of the peak size of segments in use,
-#define MI_SEGMENT_CACHE_FRACTION (8)
+static bool mi_segment_commitx(mi_segment_t* segment, bool commit, uint8_t* p, size_t size, mi_stats_t* stats) {    
+  mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask));
 
-// note: returned segment may be partially reset
-static mi_segment_t* mi_segment_cache_pop(size_t segment_size, mi_segments_tld_t* tld) {
-  if (segment_size != 0 && segment_size != MI_SEGMENT_SIZE) return NULL;
-  mi_segment_t* segment = tld->cache;
-  if (segment == NULL) return NULL;
-  tld->cache_count--;
-  tld->cache = segment->next;
-  segment->next = NULL;
-  mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE);
-  _mi_stat_decrease(&tld->stats->segments_cache, 1);
-  return segment;
+  // try to commit in at least MI_MINIMAL_COMMIT_SIZE sizes.
+  /*
+  if (commit && size > 0) {
+    const size_t csize = _mi_align_up(size, MI_MINIMAL_COMMIT_SIZE);
+    if (p + csize <= mi_segment_end(segment)) {
+      size = csize;
+    }
+  }
+  */
+  // commit liberal, but decommit conservative
+  uint8_t* start = NULL;
+  size_t   full_size = 0;
+  mi_commit_mask_t mask;
+  mi_segment_commit_mask(segment, !commit/*conservative*/, p, size, &start, &full_size, &mask);
+  if (mi_commit_mask_is_empty(&mask) || full_size==0) return true;
+
+  if (commit && !mi_commit_mask_all_set(&segment->commit_mask, &mask)) {
+    bool is_zero = false;
+    mi_commit_mask_t cmask;
+    mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask);
+    _mi_stat_decrease(&_mi_stats_main.committed, _mi_commit_mask_committed_size(&cmask, MI_SEGMENT_SIZE)); // adjust for overlap
+    if (!_mi_os_commit(start,full_size,&is_zero,stats)) return false;    
+    mi_commit_mask_set(&segment->commit_mask, &mask);     
+  }
+  else if (!commit && mi_commit_mask_any_set(&segment->commit_mask, &mask)) {
+    mi_assert_internal((void*)start != (void*)segment);
+    //mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &mask));
+
+    mi_commit_mask_t cmask;
+    mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask);
+    _mi_stat_increase(&_mi_stats_main.committed, full_size - _mi_commit_mask_committed_size(&cmask, MI_SEGMENT_SIZE)); // adjust for overlap
+    if (segment->allow_decommit) { 
+      _mi_os_decommit(start, full_size, stats); // ok if this fails
+    } 
+    mi_commit_mask_clear(&segment->commit_mask, &mask);
+  }
+  // increase expiration of reusing part of the delayed decommit
+  if (commit && mi_commit_mask_any_set(&segment->decommit_mask, &mask)) {
+    segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_decommit_delay);
+  }
+  // always undo delayed decommits
+  mi_commit_mask_clear(&segment->decommit_mask, &mask);
+  return true;
 }
 
-static bool mi_segment_cache_full(mi_segments_tld_t* tld)
-{
-  // if (tld->count == 1 && tld->cache_count==0) return false; // always cache at least the final segment of a thread
-  size_t max_cache = mi_option_get(mi_option_segment_cache);
-  if (tld->cache_count < max_cache
-       && tld->cache_count < (1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION)) // at least allow a 1 element cache
-     ) {
-    return false;
-  }
-  // take the opportunity to reduce the segment cache if it is too large (now)
-  // TODO: this never happens as we check against peak usage, should we use current usage instead?
-  while (tld->cache_count > max_cache) { //(1 + (tld->peak_count / MI_SEGMENT_CACHE_FRACTION))) {
-    mi_segment_t* segment = mi_segment_cache_pop(0,tld);
-    mi_assert_internal(segment != NULL);
-    if (segment != NULL) mi_segment_os_free(segment, segment->segment_size, tld);
+static bool mi_segment_ensure_committed(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) {
+  mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask));
+  // note: assumes commit_mask is always full for huge segments as otherwise the commit mask bits can overflow
+  if (mi_commit_mask_is_full(&segment->commit_mask) && mi_commit_mask_is_empty(&segment->decommit_mask)) return true; // fully committed
+  return mi_segment_commitx(segment,true,p,size,stats);
+}
+
+static void mi_segment_perhaps_decommit(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) {
+  if (!segment->allow_decommit) return;
+  if (mi_option_get(mi_option_decommit_delay) == 0) {
+    mi_segment_commitx(segment, false, p, size, stats);
   }
-  return true;
+  else {
+    // register for future decommit in the decommit mask
+    uint8_t* start = NULL;
+    size_t   full_size = 0;
+    mi_commit_mask_t mask; 
+    mi_segment_commit_mask(segment, true /*conservative*/, p, size, &start, &full_size, &mask);
+    if (mi_commit_mask_is_empty(&mask) || full_size==0) return;
+    
+    // update delayed commit
+    mi_assert_internal(segment->decommit_expire > 0 || mi_commit_mask_is_empty(&segment->decommit_mask));      
+    mi_commit_mask_t cmask;
+    mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask);  // only decommit what is committed; span_free may try to decommit more
+    mi_commit_mask_set(&segment->decommit_mask, &cmask);
+    mi_msecs_t now = _mi_clock_now();    
+    if (segment->decommit_expire == 0) {
+      // no previous decommits, initialize now
+      segment->decommit_expire = now + mi_option_get(mi_option_decommit_delay);
+    }
+    else if (segment->decommit_expire <= now) {
+      // previous decommit mask already expired
+      // mi_segment_delayed_decommit(segment, true, stats);
+      segment->decommit_expire = now + mi_option_get(mi_option_decommit_extend_delay); // (mi_option_get(mi_option_decommit_delay) / 8); // wait a tiny bit longer in case there is a series of free's
+    }
+    else {
+      // previous decommit mask is not yet expired, increase the expiration by a bit.
+      segment->decommit_expire += mi_option_get(mi_option_decommit_extend_delay);
+    }
+  }  
 }
 
-static bool mi_segment_cache_push(mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_assert_internal(!mi_segment_is_in_free_queue(segment, tld));
-  mi_assert_internal(segment->next == NULL);
-  if (segment->segment_size != MI_SEGMENT_SIZE || mi_segment_cache_full(tld)) {
-    return false;
-  }
-  mi_assert_internal(segment->segment_size == MI_SEGMENT_SIZE);
-  segment->next = tld->cache;
-  tld->cache = segment;
-  tld->cache_count++;
-  _mi_stat_increase(&tld->stats->segments_cache,1);
-  return true;
+static void mi_segment_delayed_decommit(mi_segment_t* segment, bool force, mi_stats_t* stats) {
+  if (!segment->allow_decommit || mi_commit_mask_is_empty(&segment->decommit_mask)) return;
+  mi_msecs_t now = _mi_clock_now();
+  if (!force && now < segment->decommit_expire) return;
+
+  mi_commit_mask_t mask = segment->decommit_mask;
+  segment->decommit_expire = 0;
+  mi_commit_mask_create_empty(&segment->decommit_mask);
+
+  size_t idx;
+  size_t count;
+  mi_commit_mask_foreach(&mask, idx, count) {
+    // if found, decommit that sequence
+    if (count > 0) {
+      uint8_t* p = (uint8_t*)segment + (idx*MI_COMMIT_SIZE);
+      size_t size = count * MI_COMMIT_SIZE;
+      mi_segment_commitx(segment, false, p, size, stats);
+    }
+  }
+  mi_commit_mask_foreach_end()
+  mi_assert_internal(mi_commit_mask_is_empty(&segment->decommit_mask));
 }
 
-// called by threads that are terminating to free cached segments
-void _mi_segment_thread_collect(mi_segments_tld_t* tld) {
-  mi_segment_t* segment;
-  while ((segment = mi_segment_cache_pop(0,tld)) != NULL) {
-    mi_segment_os_free(segment, segment->segment_size, tld);
+
+static bool mi_segment_is_abandoned(mi_segment_t* segment) {
+  return (segment->thread_id == 0);
+}
+
+// note: can be called on abandoned segments
+static void mi_segment_span_free(mi_segment_t* segment, size_t slice_index, size_t slice_count, mi_segments_tld_t* tld) {
+  mi_assert_internal(slice_index < segment->slice_entries);
+  mi_span_queue_t* sq = (segment->kind == MI_SEGMENT_HUGE || mi_segment_is_abandoned(segment) 
+                          ? NULL : mi_span_queue_for(slice_count,tld));
+  if (slice_count==0) slice_count = 1;
+  mi_assert_internal(slice_index + slice_count - 1 < segment->slice_entries);
+
+  // set first and last slice (the intermediates can be undetermined)
+  mi_slice_t* slice = &segment->slices[slice_index];
+  slice->slice_count = (uint32_t)slice_count;
+  mi_assert_internal(slice->slice_count == slice_count); // no overflow?
+  slice->slice_offset = 0;
+  if (slice_count > 1) {
+    mi_slice_t* last = &segment->slices[slice_index + slice_count - 1];
+    last->slice_count = 0;
+    last->slice_offset = (uint32_t)(sizeof(mi_page_t)*(slice_count - 1));
+    last->xblock_size = 0;
+  }
+
+  // perhaps decommit
+  mi_segment_perhaps_decommit(segment,mi_slice_start(slice),slice_count*MI_SEGMENT_SLICE_SIZE,tld->stats);
+  
+  // and push it on the free page queue (if it was not a huge page)
+  if (sq != NULL) mi_span_queue_push( sq, slice );
+             else slice->xblock_size = 0; // mark huge page as free anyways
+}
+
+/*
+// called from reclaim to add existing free spans
+static void mi_segment_span_add_free(mi_slice_t* slice, mi_segments_tld_t* tld) {
+  mi_segment_t* segment = _mi_ptr_segment(slice);
+  mi_assert_internal(slice->xblock_size==0 && slice->slice_count>0 && slice->slice_offset==0);
+  size_t slice_index = mi_slice_index(slice);
+  mi_segment_span_free(segment,slice_index,slice->slice_count,tld);
+}
+*/
+
+static void mi_segment_span_remove_from_queue(mi_slice_t* slice, mi_segments_tld_t* tld) {
+  mi_assert_internal(slice->slice_count > 0 && slice->slice_offset==0 && slice->xblock_size==0);
+  mi_assert_internal(_mi_ptr_segment(slice)->kind != MI_SEGMENT_HUGE);
+  mi_span_queue_t* sq = mi_span_queue_for(slice->slice_count, tld);
+  mi_span_queue_delete(sq, slice);
+}
+
+// note: can be called on abandoned segments
+static mi_slice_t* mi_segment_span_free_coalesce(mi_slice_t* slice, mi_segments_tld_t* tld) {
+  mi_assert_internal(slice != NULL && slice->slice_count > 0 && slice->slice_offset == 0);
+  mi_segment_t* segment = _mi_ptr_segment(slice);
+  bool is_abandoned = mi_segment_is_abandoned(segment);
+
+  // for huge pages, just mark as free but don't add to the queues
+  if (segment->kind == MI_SEGMENT_HUGE) {
+    mi_assert_internal(segment->used == 1);  // decreased right after this call in `mi_segment_page_clear`
+    slice->xblock_size = 0;  // mark as free anyways
+    // we should mark the last slice `xblock_size=0` now to maintain invariants but we skip it to 
+    // avoid a possible cache miss (and the segment is about to be freed)
+    return slice;
+  }
+
+  // otherwise coalesce the span and add to the free span queues
+  size_t slice_count = slice->slice_count;
+  mi_slice_t* next = slice + slice->slice_count;
+  mi_assert_internal(next <= mi_segment_slices_end(segment));
+  if (next < mi_segment_slices_end(segment) && next->xblock_size==0) {
+    // free next block -- remove it from free and merge
+    mi_assert_internal(next->slice_count > 0 && next->slice_offset==0);
+    slice_count += next->slice_count; // extend
+    if (!is_abandoned) { mi_segment_span_remove_from_queue(next, tld); }
+  }
+  if (slice > segment->slices) {
+    mi_slice_t* prev = mi_slice_first(slice - 1);
+    mi_assert_internal(prev >= segment->slices);
+    if (prev->xblock_size==0) {
+      // free previous slice -- remove it from free and merge
+      mi_assert_internal(prev->slice_count > 0 && prev->slice_offset==0);
+      slice_count += prev->slice_count;
+      if (!is_abandoned) { mi_segment_span_remove_from_queue(prev, tld); }
+      slice = prev;
+    }
   }
-  mi_assert_internal(tld->cache_count == 0);
-  mi_assert_internal(tld->cache == NULL);
-#if MI_DEBUG>=2
-  if (!_mi_is_main_thread()) {
-    mi_assert_internal(tld->pages_reset.first == NULL);
-    mi_assert_internal(tld->pages_reset.last == NULL);
+
+  // and add the new free page
+  mi_segment_span_free(segment, mi_slice_index(slice), slice_count, tld);
+  return slice;
+}
+
+
+static void mi_segment_slice_split(mi_segment_t* segment, mi_slice_t* slice, size_t slice_count, mi_segments_tld_t* tld) {
+  mi_assert_internal(_mi_ptr_segment(slice)==segment);
+  mi_assert_internal(slice->slice_count >= slice_count);
+  mi_assert_internal(slice->xblock_size > 0); // no more in free queue
+  if (slice->slice_count <= slice_count) return;
+  mi_assert_internal(segment->kind != MI_SEGMENT_HUGE);
+  size_t next_index = mi_slice_index(slice) + slice_count;
+  size_t next_count = slice->slice_count - slice_count;
+  mi_segment_span_free(segment, next_index, next_count, tld);
+  slice->slice_count = (uint32_t)slice_count;
+}
+
+// Note: may still return NULL if committing the memory failed
+static mi_page_t* mi_segment_span_allocate(mi_segment_t* segment, size_t slice_index, size_t slice_count, mi_segments_tld_t* tld) {
+  mi_assert_internal(slice_index < segment->slice_entries);
+  mi_slice_t* slice = &segment->slices[slice_index];
+  mi_assert_internal(slice->xblock_size==0 || slice->xblock_size==1);
+
+  // commit before changing the slice data
+  if (!mi_segment_ensure_committed(segment, _mi_segment_page_start_from_slice(segment, slice, 0, NULL), slice_count * MI_SEGMENT_SLICE_SIZE, tld->stats)) {
+    return NULL;  // commit failed!
+  }
+
+  // convert the slices to a page
+  slice->slice_offset = 0;
+  slice->slice_count = (uint32_t)slice_count;
+  mi_assert_internal(slice->slice_count == slice_count);
+  const size_t bsize = slice_count * MI_SEGMENT_SLICE_SIZE;
+  slice->xblock_size = (uint32_t)(bsize >= MI_HUGE_BLOCK_SIZE ? MI_HUGE_BLOCK_SIZE : bsize);
+  mi_page_t*  page = mi_slice_to_page(slice);
+  mi_assert_internal(mi_page_block_size(page) == bsize);
+
+  // set slice back pointers for the first MI_MAX_SLICE_OFFSET entries
+  size_t extra = slice_count-1;
+  if (extra > MI_MAX_SLICE_OFFSET) extra = MI_MAX_SLICE_OFFSET;
+  if (slice_index + extra >= segment->slice_entries) extra = segment->slice_entries - slice_index - 1;  // huge objects may have more slices than avaiable entries in the segment->slices
+  slice++;
+  for (size_t i = 1; i <= extra; i++, slice++) {
+    slice->slice_offset = (uint32_t)(sizeof(mi_slice_t)*i);
+    slice->slice_count = 0;
+    slice->xblock_size = 1;
+  }
+
+  // and also for the last one (if not set already) (the last one is needed for coalescing)
+  // note: the cast is needed for ubsan since the index can be larger than MI_SLICES_PER_SEGMENT for huge allocations (see #543)
+  mi_slice_t* last = &((mi_slice_t*)segment->slices)[slice_index + slice_count - 1]; 
+  if (last < mi_segment_slices_end(segment) && last >= slice) {
+    last->slice_offset = (uint32_t)(sizeof(mi_slice_t)*(slice_count-1));
+    last->slice_count = 0;
+    last->xblock_size = 1;
   }
-#endif
+  
+  // and initialize the page
+  page->is_reset = false;
+  page->is_committed = true;
+  segment->used++;
+  return page;
+}
+
+static mi_page_t* mi_segments_page_find_and_allocate(size_t slice_count, mi_segments_tld_t* tld) {
+  mi_assert_internal(slice_count*MI_SEGMENT_SLICE_SIZE <= MI_LARGE_OBJ_SIZE_MAX);
+  // search from best fit up
+  mi_span_queue_t* sq = mi_span_queue_for(slice_count, tld);
+  if (slice_count == 0) slice_count = 1;
+  while (sq <= &tld->spans[MI_SEGMENT_BIN_MAX]) {
+    for (mi_slice_t* slice = sq->first; slice != NULL; slice = slice->next) {
+      if (slice->slice_count >= slice_count) {
+        // found one
+        mi_span_queue_delete(sq, slice);
+        mi_segment_t* segment = _mi_ptr_segment(slice);
+        if (slice->slice_count > slice_count) {
+          mi_segment_slice_split(segment, slice, slice_count, tld);
+        }
+        mi_assert_internal(slice != NULL && slice->slice_count == slice_count && slice->xblock_size > 0);
+        mi_page_t* page = mi_segment_span_allocate(segment, mi_slice_index(slice), slice->slice_count, tld);
+        if (page == NULL) {
+          // commit failed; return NULL but first restore the slice
+          mi_segment_span_free_coalesce(slice, tld);
+          return NULL;
+        }
+        return page;        
+      }
+    }
+    sq++;
+  }
+  // could not find a page..
+  return NULL;
 }
 
 
@@ -548,287 +757,248 @@ void _mi_segment_thread_collect(mi_segments_tld_t* tld) {
 ----------------------------------------------------------- */
 
 // Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` .
-static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
+static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_segments_tld_t* tld, mi_os_tld_t* os_tld, mi_page_t** huge_page)
 {
-  // the segment parameter is non-null if it came from our cache
-  mi_assert_internal(segment==NULL || (required==0 && page_kind <= MI_PAGE_LARGE));
-
+  mi_assert_internal((required==0 && huge_page==NULL) || (required>0 && huge_page != NULL));
+  mi_assert_internal((segment==NULL) || (segment!=NULL && required==0));
   // calculate needed sizes first
-  size_t capacity;
-  if (page_kind == MI_PAGE_HUGE) {
-    mi_assert_internal(page_shift == MI_SEGMENT_SHIFT && required > 0);
-    capacity = 1;
-  }
-  else {
-    mi_assert_internal(required == 0);
-    size_t page_size = (size_t)1 << page_shift;
-    capacity = MI_SEGMENT_SIZE / page_size;
-    mi_assert_internal(MI_SEGMENT_SIZE % page_size == 0);
-    mi_assert_internal(capacity >= 1 && capacity <= MI_SMALL_PAGES_PER_SEGMENT);
-  }
-  size_t info_size;
+  size_t info_slices;
   size_t pre_size;
-  size_t segment_size = mi_segment_size(capacity, required, &pre_size, &info_size);
-  mi_assert_internal(segment_size >= required);
-
-  // Initialize parameters
-  const bool eager_delayed = (page_kind <= MI_PAGE_MEDIUM && tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay));
-  const bool eager  = !eager_delayed && mi_option_is_enabled(mi_option_eager_commit);
-  bool commit = eager; // || (page_kind >= MI_PAGE_LARGE);
-  bool pages_still_good = false;
+  const size_t segment_slices = mi_segment_calculate_slices(required, &pre_size, &info_slices);
+  const size_t slice_entries = (segment_slices > MI_SLICES_PER_SEGMENT ? MI_SLICES_PER_SEGMENT : segment_slices);
+  const size_t segment_size = segment_slices * MI_SEGMENT_SLICE_SIZE;
+
+  // Commit eagerly only if not the first N lazy segments (to reduce impact of many threads that allocate just a little)
+  const bool eager_delay = (// !_mi_os_has_overcommit() &&             // never delay on overcommit systems
+                            _mi_current_thread_count() > 1 &&       // do not delay for the first N threads
+                            tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay));
+  const bool eager = !eager_delay && mi_option_is_enabled(mi_option_eager_commit);
+  bool commit = eager || (required > 0); 
+  
+  // Try to get from our cache first
   bool is_zero = false;
-
-  // Try to get it from our thread local cache first
+  const bool commit_info_still_good = (segment != NULL);
+  mi_commit_mask_t commit_mask;
+  mi_commit_mask_t decommit_mask;
   if (segment != NULL) {
-    // came from cache
-    mi_assert_internal(segment->segment_size == segment_size);
-    if (page_kind <= MI_PAGE_MEDIUM && segment->page_kind == page_kind && segment->segment_size == segment_size) {
-      pages_still_good = true;
-    }
-    else
-    {
-      if (MI_SECURE!=0) {
-        mi_assert_internal(!segment->mem_is_fixed);
-        mi_segment_protect(segment, false, tld->os); // reset protection if the page kind differs
-      }
-      // different page kinds; unreset any reset pages, and unprotect
-      // TODO: optimize cache pop to return fitting pages if possible?
-      for (size_t i = 0; i < segment->capacity; i++) {
-        mi_page_t* page = &segment->pages[i];
-        if (page->is_reset) {
-          if (!commit && mi_option_is_enabled(mi_option_reset_decommits)) {
-            page->is_reset = false;
-          }
-          else {
-            mi_page_unreset(segment, page, 0, tld);  // todo: only unreset the part that was reset? (instead of the full page)
-          }
-        }
-      }
-      // ensure the initial info is committed
-      if (segment->capacity < capacity) {
-        bool commit_zero = false;
-        _mi_mem_commit(segment, pre_size, &commit_zero, tld->os);
-        if (commit_zero) is_zero = true;
-      }
-    }
+    commit_mask = segment->commit_mask;
+    decommit_mask = segment->decommit_mask;
   }
   else {
+    mi_commit_mask_create_empty(&commit_mask);
+    mi_commit_mask_create_empty(&decommit_mask);
+  }
+  if (segment==NULL) {
     // Allocate the segment from the OS
-    size_t memid;
-    bool   mem_large = (!eager_delayed && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy
-    segment = (mi_segment_t*)_mi_mem_alloc_aligned(segment_size, MI_SEGMENT_SIZE, &commit, &mem_large, &is_zero, &memid, os_tld);
-    if (segment == NULL) return NULL;  // failed to allocate
-    if (!commit) {
-      // ensure the initial info is committed
-      bool commit_zero = false;
-      bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os);
-      if (commit_zero) is_zero = true;
-      if (!ok) {
-        // commit failed; we cannot touch the memory: free the segment directly and return `NULL`
-        _mi_mem_free(segment, MI_SEGMENT_SIZE, memid, false, false, os_tld);
-        return NULL;  
+    bool mem_large = (!eager_delay && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy    
+    bool is_pinned = false;
+    size_t memid = 0;
+    segment = (mi_segment_t*)_mi_segment_cache_pop(segment_size, &commit_mask, &decommit_mask, &mem_large, &is_pinned, &is_zero, &memid, os_tld);
+    if (segment==NULL) {
+      segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, MI_SEGMENT_SIZE, &commit, &mem_large, &is_pinned, &is_zero, &memid, os_tld);
+      if (segment == NULL) return NULL;  // failed to allocate
+      if (commit) {
+        mi_commit_mask_create_full(&commit_mask);
       }
+      else {
+        mi_commit_mask_create_empty(&commit_mask);
+      }
+    }    
+    mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0);
+
+    const size_t commit_needed = _mi_divide_up(info_slices*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE);
+    mi_assert_internal(commit_needed>0);
+    mi_commit_mask_t commit_needed_mask;
+    mi_commit_mask_create(0, commit_needed, &commit_needed_mask);
+    if (!mi_commit_mask_all_set(&commit_mask, &commit_needed_mask)) {
+      // at least commit the info slices
+      mi_assert_internal(commit_needed*MI_COMMIT_SIZE >= info_slices*MI_SEGMENT_SLICE_SIZE);
+      bool ok = _mi_os_commit(segment, commit_needed*MI_COMMIT_SIZE, &is_zero, tld->stats);
+      if (!ok) return NULL; // failed to commit   
+      mi_commit_mask_set(&commit_mask, &commit_needed_mask); 
     }
     segment->memid = memid;
-    segment->mem_is_fixed = mem_large;
-    segment->mem_is_committed = commit;
-    mi_segments_track_size((long)segment_size, tld);
-  }
-  mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0);
-  mi_assert_internal(segment->mem_is_fixed ? segment->mem_is_committed : true);  
-  if (!pages_still_good) {
-    // zero the segment info (but not the `mem` fields)
-    ptrdiff_t ofs = offsetof(mi_segment_t, next);
-    memset((uint8_t*)segment + ofs, 0, info_size - ofs);
-
-    // initialize pages info
-    for (uint8_t i = 0; i < capacity; i++) {
-      segment->pages[i].segment_idx = i;
-      segment->pages[i].is_reset = false;
-      segment->pages[i].is_committed = commit;
-      segment->pages[i].is_zero_init = is_zero;
-    }
+    segment->mem_is_pinned = is_pinned;
+    segment->mem_is_large = mem_large;
+    segment->mem_is_committed = mi_commit_mask_is_full(&commit_mask);
+    mi_segments_track_size((long)(segment_size), tld);
+    _mi_segment_map_allocated_at(segment);
   }
-  else {
-    // zero the segment info but not the pages info (and mem fields)
+
+  // zero the segment info? -- not always needed as it is zero initialized from the OS 
+  mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL);  // tsan
+  if (!is_zero) {
     ptrdiff_t ofs = offsetof(mi_segment_t, next);
-    memset((uint8_t*)segment + ofs, 0, offsetof(mi_segment_t,pages) - ofs);
+    size_t    prefix = offsetof(mi_segment_t, slices) - ofs;
+    memset((uint8_t*)segment+ofs, 0, prefix + sizeof(mi_slice_t)*segment_slices);
+  }
+
+  if (!commit_info_still_good) {
+    segment->commit_mask = commit_mask; // on lazy commit, the initial part is always committed
+    segment->allow_decommit = (mi_option_is_enabled(mi_option_allow_decommit) && !segment->mem_is_pinned && !segment->mem_is_large);    
+    if (segment->allow_decommit) {
+      segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_decommit_delay);
+      segment->decommit_mask = decommit_mask;
+      mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask));
+      #if MI_DEBUG>2
+      const size_t commit_needed = _mi_divide_up(info_slices*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE);
+      mi_commit_mask_t commit_needed_mask;
+      mi_commit_mask_create(0, commit_needed, &commit_needed_mask);
+      mi_assert_internal(!mi_commit_mask_any_set(&segment->decommit_mask, &commit_needed_mask));
+      #endif
+    }    
+    else {
+      mi_assert_internal(mi_commit_mask_is_empty(&decommit_mask));
+      segment->decommit_expire = 0;
+      mi_commit_mask_create_empty( &segment->decommit_mask );
+      mi_assert_internal(mi_commit_mask_is_empty(&segment->decommit_mask));
+    }
   }
+  
 
-  // initialize
-  segment->page_kind  = page_kind;
-  segment->capacity   = capacity;
-  segment->page_shift = page_shift;
-  segment->segment_size = segment_size;
-  segment->segment_info_size = pre_size;
-  segment->thread_id  = _mi_thread_id();
+  // initialize segment info
+  segment->segment_slices = segment_slices;
+  segment->segment_info_slices = info_slices;
+  segment->thread_id = _mi_thread_id();
   segment->cookie = _mi_ptr_cookie(segment);
-  // _mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size);
+  segment->slice_entries = slice_entries;
+  segment->kind = (required == 0 ? MI_SEGMENT_NORMAL : MI_SEGMENT_HUGE);
 
-  // set protection
-  mi_segment_protect(segment, true, tld->os);
+  // memset(segment->slices, 0, sizeof(mi_slice_t)*(info_slices+1));
+  _mi_stat_increase(&tld->stats->page_committed, mi_segment_info_size(segment));
 
-  // insert in free lists for small and medium pages
-  if (page_kind <= MI_PAGE_MEDIUM) {
-    mi_segment_insert_in_free_queue(segment, tld);
+  // set up guard pages
+  size_t guard_slices = 0;
+  if (MI_SECURE>0) {
+    // in secure mode, we set up a protected page in between the segment info
+    // and the page data, and at the end of the segment.
+    size_t os_pagesize = _mi_os_page_size();    
+    mi_assert_internal(mi_segment_info_size(segment) - os_pagesize >= pre_size);
+    _mi_os_protect((uint8_t*)segment + mi_segment_info_size(segment) - os_pagesize, os_pagesize);
+    uint8_t* end = (uint8_t*)segment + mi_segment_size(segment) - os_pagesize;
+    mi_segment_ensure_committed(segment, end, os_pagesize, tld->stats);
+    _mi_os_protect(end, os_pagesize);
+    if (slice_entries == segment_slices) segment->slice_entries--; // don't use the last slice :-(
+    guard_slices = 1;
+  }
+
+  // reserve first slices for segment info
+  mi_page_t* page0 = mi_segment_span_allocate(segment, 0, info_slices, tld);
+  mi_assert_internal(page0!=NULL); if (page0==NULL) return NULL; // cannot fail as we always commit in advance  
+  mi_assert_internal(segment->used == 1);
+  segment->used = 0; // don't count our internal slices towards usage
+  
+  // initialize initial free pages
+  if (segment->kind == MI_SEGMENT_NORMAL) { // not a huge page
+    mi_assert_internal(huge_page==NULL);
+    mi_segment_span_free(segment, info_slices, segment->slice_entries - info_slices, tld);
+  }
+  else {
+    mi_assert_internal(huge_page!=NULL);
+    mi_assert_internal(mi_commit_mask_is_empty(&segment->decommit_mask));
+    mi_assert_internal(mi_commit_mask_is_full(&segment->commit_mask));
+    *huge_page = mi_segment_span_allocate(segment, info_slices, segment_slices - info_slices - guard_slices, tld);
+    mi_assert_internal(*huge_page != NULL); // cannot fail as we commit in advance 
   }
 
-  //fprintf(stderr,"mimalloc: alloc segment at %p\n", (void*)segment);
+  mi_assert_expensive(mi_segment_is_valid(segment,tld));
   return segment;
 }
 
-static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
-  return mi_segment_init(NULL, required, page_kind, page_shift, tld, os_tld);
-}
 
-static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) {
-  UNUSED(force);
-  mi_assert(segment != NULL);
-  // note: don't reset pages even on abandon as the whole segment is freed? (and ready for reuse)
-  bool force_reset = (force && mi_option_is_enabled(mi_option_abandoned_page_reset));
-  mi_pages_reset_remove_all_in_segment(segment, force_reset, tld);
-  mi_segment_remove_from_free_queue(segment,tld);
-
-  mi_assert_expensive(!mi_segment_queue_contains(&tld->small_free, segment));
-  mi_assert_expensive(!mi_segment_queue_contains(&tld->medium_free, segment));
-  mi_assert(segment->next == NULL);
-  mi_assert(segment->prev == NULL);
-  _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size);
-
-  if (!force && mi_segment_cache_push(segment, tld)) {
-    // it is put in our cache
-  }
-  else {
-    // otherwise return it to the OS
-    mi_segment_os_free(segment, segment->segment_size, tld);
-  }
+// Allocate a segment from the OS aligned to `MI_SEGMENT_SIZE` .
+static mi_segment_t* mi_segment_alloc(size_t required, mi_segments_tld_t* tld, mi_os_tld_t* os_tld, mi_page_t** huge_page) {
+  return mi_segment_init(NULL, required, tld, os_tld, huge_page);
 }
 
-/* -----------------------------------------------------------
-  Free page management inside a segment
------------------------------------------------------------ */
-
 
-static bool mi_segment_has_free(const mi_segment_t* segment) {
-  return (segment->used < segment->capacity);
-}
-
-static bool mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) {
-  mi_assert_internal(_mi_page_segment(page) == segment);
-  mi_assert_internal(!page->segment_in_use);
-  mi_pages_reset_remove(page, tld);
-  // check commit
-  if (!page->is_committed) {
-    mi_assert_internal(!segment->mem_is_fixed);
-    mi_assert_internal(!page->is_reset);    
-    size_t psize;
-    uint8_t* start = mi_segment_raw_page_start(segment, page, &psize);
-    bool is_zero = false;
-    const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0);
-    bool ok = _mi_mem_commit(start, psize + gsize, &is_zero, tld->os);
-    if (!ok) return false; // failed to commit!
-    if (gsize > 0) { mi_segment_protect_range(start + psize, gsize, true); }
-    if (is_zero) { page->is_zero_init = true; }
-    page->is_committed = true;
-  }
-  // set in-use before doing unreset to prevent delayed reset
-  page->segment_in_use = true;
-  segment->used++;
-  // check reset
-  if (page->is_reset) {
-    mi_assert_internal(!segment->mem_is_fixed);
-    bool ok = mi_page_unreset(segment, page, 0, tld); 
-    if (!ok) {
-      page->segment_in_use = false;
-      segment->used--;
-      return false;
+static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) {
+  MI_UNUSED(force);
+  mi_assert_internal(segment != NULL);
+  mi_assert_internal(segment->next == NULL);
+  mi_assert_internal(segment->used == 0);
+
+  // Remove the free pages
+  mi_slice_t* slice = &segment->slices[0];
+  const mi_slice_t* end = mi_segment_slices_end(segment);
+  size_t page_count = 0;
+  while (slice < end) {
+    mi_assert_internal(slice->slice_count > 0);
+    mi_assert_internal(slice->slice_offset == 0);
+    mi_assert_internal(mi_slice_index(slice)==0 || slice->xblock_size == 0); // no more used pages ..
+    if (slice->xblock_size == 0 && segment->kind != MI_SEGMENT_HUGE) {
+      mi_segment_span_remove_from_queue(slice, tld);
     }
+    page_count++;
+    slice = slice + slice->slice_count;
   }
-  mi_assert_internal(page->segment_in_use);
-  mi_assert_internal(segment->used <= segment->capacity);
-  if (segment->used == segment->capacity && segment->page_kind <= MI_PAGE_MEDIUM) {
-    // if no more free pages, remove from the queue
-    mi_assert_internal(!mi_segment_has_free(segment));
-    mi_segment_remove_from_free_queue(segment, tld);
-  }
-  return true;
+  mi_assert_internal(page_count == 2); // first page is allocated by the segment itself
+
+  // stats
+  _mi_stat_decrease(&tld->stats->page_committed, mi_segment_info_size(segment));
+
+  // return it to the OS
+  mi_segment_os_free(segment, tld);
 }
 
 
 /* -----------------------------------------------------------
-   Free
+   Page Free
 ----------------------------------------------------------- */
 
 static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld);
 
-// clear page data; can be called on abandoned segments
-static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, bool allow_reset, mi_segments_tld_t* tld)
-{
-  mi_assert_internal(page->segment_in_use);
+// note: can be called on abandoned pages
+static mi_slice_t* mi_segment_page_clear(mi_page_t* page, mi_segments_tld_t* tld) {
+  mi_assert_internal(page->xblock_size > 0);
   mi_assert_internal(mi_page_all_free(page));
-  mi_assert_internal(page->is_committed);
-  mi_assert_internal(mi_page_not_in_queue(page, tld));
-
+  mi_segment_t* segment = _mi_ptr_segment(page);
+  mi_assert_internal(segment->used > 0);
+  
   size_t inuse = page->capacity * mi_page_block_size(page);
   _mi_stat_decrease(&tld->stats->page_committed, inuse);
   _mi_stat_decrease(&tld->stats->pages, 1);
 
-  // calculate the used size from the raw (non-aligned) start of the page
-  //size_t pre_size;
-  //_mi_segment_page_start(segment, page, page->block_size, NULL, &pre_size);
-  //size_t used_size = pre_size + (page->capacity * page->block_size);
+  // reset the page memory to reduce memory pressure?
+  if (!segment->mem_is_pinned && !page->is_reset && mi_option_is_enabled(mi_option_page_reset)) {
+    size_t psize;
+    uint8_t* start = _mi_page_start(segment, page, &psize);
+    page->is_reset = true;
+    _mi_os_reset(start, psize, tld->stats);
+  }
 
+  // zero the page data, but not the segment fields
   page->is_zero_init = false;
-  page->segment_in_use = false;
-
-  // reset the page memory to reduce memory pressure?
-  // note: must come after setting `segment_in_use` to false but before block_size becomes 0
-  //mi_page_reset(segment, page, 0 /*used_size*/, tld);
-
-  // zero the page data, but not the segment fields and capacity, and block_size (for page size calculations)
-  uint32_t block_size = page->xblock_size;
-  uint16_t capacity = page->capacity;
-  uint16_t reserved = page->reserved;
-  ptrdiff_t ofs = offsetof(mi_page_t,capacity);
+  ptrdiff_t ofs = offsetof(mi_page_t, capacity);
   memset((uint8_t*)page + ofs, 0, sizeof(*page) - ofs);
-  page->capacity = capacity;
-  page->reserved = reserved;
-  page->xblock_size = block_size;
-  segment->used--;
+  page->xblock_size = 1;
 
-  // add to the free page list for reuse/reset
-  if (allow_reset) {
-    mi_pages_reset_add(segment, page, tld);
-  }
-
-  page->capacity = 0;  // after reset there can be zero'd now
-  page->reserved = 0;
+  // and free it
+  mi_slice_t* slice = mi_segment_span_free_coalesce(mi_page_to_slice(page), tld);  
+  segment->used--;
+  // cannot assert segment valid as it is called during reclaim
+  // mi_assert_expensive(mi_segment_is_valid(segment, tld));
+  return slice;
 }
 
 void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld)
 {
   mi_assert(page != NULL);
+
   mi_segment_t* segment = _mi_page_segment(page);
   mi_assert_expensive(mi_segment_is_valid(segment,tld));
-  mi_reset_delayed(tld);
 
   // mark it as free now
-  mi_segment_page_clear(segment, page, true, tld);
+  mi_segment_page_clear(page, tld);
+  mi_assert_expensive(mi_segment_is_valid(segment, tld));
 
   if (segment->used == 0) {
     // no more used pages; remove from the free list and free the segment
     mi_segment_free(segment, force, tld);
   }
-  else {
-    if (segment->used == segment->abandoned) {
-      // only abandoned pages; remove from free list and abandon
-      mi_segment_abandon(segment,tld);
-    }
-    else if (segment->used + 1 == segment->capacity) {
-      mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM); // for now we only support small and medium pages
-      // move back to segments  free list
-      mi_segment_insert_in_free_queue(segment,tld);
-    }
+  else if (segment->used == segment->abandoned) {
+    // only abandoned pages; remove from free list and abandon
+    mi_segment_abandon(segment,tld);
   }
 }
 
@@ -837,7 +1007,7 @@ void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld)
 Abandonment
 
 When threads terminate, they can leave segments with
-live blocks (reached through other threads). Such segments
+live blocks (reachable through other threads). Such segments
 are "abandoned" and will be reclaimed by other threads to
 reuse their pages and/or free them eventually
 
@@ -852,11 +1022,11 @@ or decommitting segments that have a pending read operation.
 
 Note: the current implementation is one possible design;
 another way might be to keep track of abandoned segments
-in the regions. This would have the advantage of keeping
+in the arenas/segment_cache's. This would have the advantage of keeping
 all concurrent code in one place and not needing to deal
 with ABA issues. The drawback is that it is unclear how to
 scan abandoned segments efficiently in that case as they
-would be spread among all other segments in the regions.
+would be spread among all other segments in the arenas.
 ----------------------------------------------------------- */
 
 // Use the bottom 20-bits (on 64-bit) of the aligned segment pointers
@@ -877,84 +1047,98 @@ static mi_tagged_segment_t mi_tagged_segment(mi_segment_t* segment, mi_tagged_se
 // This is a list of visited abandoned pages that were full at the time.
 // this list migrates to `abandoned` when that becomes NULL. The use of
 // this list reduces contention and the rate at which segments are visited.
-static mi_decl_cache_align volatile _Atomic(mi_segment_t*)       abandoned_visited; // = NULL
+static mi_decl_cache_align _Atomic(mi_segment_t*)       abandoned_visited; // = NULL
 
 // The abandoned page list (tagged as it supports pop)
-static mi_decl_cache_align volatile _Atomic(mi_tagged_segment_t) abandoned;         // = NULL
+static mi_decl_cache_align _Atomic(mi_tagged_segment_t) abandoned;         // = NULL
+
+// Maintain these for debug purposes (these counts may be a bit off)
+static mi_decl_cache_align _Atomic(size_t)           abandoned_count; 
+static mi_decl_cache_align _Atomic(size_t)           abandoned_visited_count;
 
 // We also maintain a count of current readers of the abandoned list
 // in order to prevent resetting/decommitting segment memory if it might
 // still be read.
-static mi_decl_cache_align volatile _Atomic(uintptr_t)           abandoned_readers; // = 0
+static mi_decl_cache_align _Atomic(size_t)           abandoned_readers; // = 0
 
 // Push on the visited list
 static void mi_abandoned_visited_push(mi_segment_t* segment) {
   mi_assert_internal(segment->thread_id == 0);
-  mi_assert_internal(segment->abandoned_next == NULL);
-  mi_assert_internal(segment->next == NULL && segment->prev == NULL);
+  mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t,&segment->abandoned_next) == NULL);
+  mi_assert_internal(segment->next == NULL);
   mi_assert_internal(segment->used > 0);
-  mi_segment_t* anext;
+  mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited);
   do {
-    anext = mi_atomic_read_ptr_relaxed(mi_segment_t, &abandoned_visited);
-    segment->abandoned_next = anext;
-  } while (!mi_atomic_cas_ptr_weak(mi_segment_t, &abandoned_visited, segment, anext));
+    mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, anext);
+  } while (!mi_atomic_cas_ptr_weak_release(mi_segment_t, &abandoned_visited, &anext, segment));
+  mi_atomic_increment_relaxed(&abandoned_visited_count);
 }
 
 // Move the visited list to the abandoned list.
 static bool mi_abandoned_visited_revisit(void)
 {
   // quick check if the visited list is empty
-  if (mi_atomic_read_ptr_relaxed(mi_segment_t,&abandoned_visited)==NULL) return false;
+  if (mi_atomic_load_ptr_relaxed(mi_segment_t, &abandoned_visited) == NULL) return false;
 
   // grab the whole visited list
-  mi_segment_t* first = mi_atomic_exchange_ptr(mi_segment_t, &abandoned_visited, NULL);
+  mi_segment_t* first = mi_atomic_exchange_ptr_acq_rel(mi_segment_t, &abandoned_visited, NULL);
   if (first == NULL) return false;
 
   // first try to swap directly if the abandoned list happens to be NULL
-  const mi_tagged_segment_t ts = mi_atomic_read_relaxed(&abandoned);
   mi_tagged_segment_t afirst;
+  mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned);
   if (mi_tagged_segment_ptr(ts)==NULL) {
+    size_t count = mi_atomic_load_relaxed(&abandoned_visited_count);
     afirst = mi_tagged_segment(first, ts);
-    if (mi_atomic_cas_strong(&abandoned, afirst, ts)) return true;
+    if (mi_atomic_cas_strong_acq_rel(&abandoned, &ts, afirst)) {
+      mi_atomic_add_relaxed(&abandoned_count, count);
+      mi_atomic_sub_relaxed(&abandoned_visited_count, count);
+      return true;
+    }
   }
 
   // find the last element of the visited list: O(n)
   mi_segment_t* last = first;
-  while (last->abandoned_next != NULL) {
-    last = last->abandoned_next;
+  mi_segment_t* next;
+  while ((next = mi_atomic_load_ptr_relaxed(mi_segment_t, &last->abandoned_next)) != NULL) {
+    last = next;
   }
 
   // and atomically prepend to the abandoned list
   // (no need to increase the readers as we don't access the abandoned segments)
-  mi_tagged_segment_t anext;
+  mi_tagged_segment_t anext = mi_atomic_load_relaxed(&abandoned);
+  size_t count;
   do {
-    anext = mi_atomic_read_relaxed(&abandoned);
-    last->abandoned_next = mi_tagged_segment_ptr(anext);
+    count = mi_atomic_load_relaxed(&abandoned_visited_count);
+    mi_atomic_store_ptr_release(mi_segment_t, &last->abandoned_next, mi_tagged_segment_ptr(anext));
     afirst = mi_tagged_segment(first, anext);
-  } while (!mi_atomic_cas_weak(&abandoned, afirst, anext));
+  } while (!mi_atomic_cas_weak_release(&abandoned, &anext, afirst));
+  mi_atomic_add_relaxed(&abandoned_count, count);
+  mi_atomic_sub_relaxed(&abandoned_visited_count, count);
   return true;
 }
 
 // Push on the abandoned list.
 static void mi_abandoned_push(mi_segment_t* segment) {
   mi_assert_internal(segment->thread_id == 0);
-  mi_assert_internal(segment->abandoned_next == NULL);
-  mi_assert_internal(segment->next == NULL && segment->prev == NULL);
+  mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL);
+  mi_assert_internal(segment->next == NULL);
   mi_assert_internal(segment->used > 0);
-  mi_tagged_segment_t ts;
   mi_tagged_segment_t next;
+  mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned);
   do {
-    ts = mi_atomic_read_relaxed(&abandoned);
-    segment->abandoned_next = mi_tagged_segment_ptr(ts);
+    mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, mi_tagged_segment_ptr(ts));
     next = mi_tagged_segment(segment, ts);
-  } while (!mi_atomic_cas_weak(&abandoned, next, ts));
+  } while (!mi_atomic_cas_weak_release(&abandoned, &ts, next));
+  mi_atomic_increment_relaxed(&abandoned_count);
 }
 
 // Wait until there are no more pending reads on segments that used to be in the abandoned list
+// called for example from `arena.c` before decommitting
 void _mi_abandoned_await_readers(void) {
-  uintptr_t n;
+  size_t n;
   do {
-    n = mi_atomic_read(&abandoned_readers);
+    n = mi_atomic_load_acquire(&abandoned_readers);
     if (n != 0) mi_atomic_yield();
   } while (n != 0);
 }
@@ -963,7 +1147,7 @@ void _mi_abandoned_await_readers(void) {
 static mi_segment_t* mi_abandoned_pop(void) {
   mi_segment_t* segment;
   // Check efficiently if it is empty (or if the visited list needs to be moved)
-  mi_tagged_segment_t ts = mi_atomic_read_relaxed(&abandoned);
+  mi_tagged_segment_t ts = mi_atomic_load_relaxed(&abandoned);
   segment = mi_tagged_segment_ptr(ts);
   if (mi_likely(segment == NULL)) {
     if (mi_likely(!mi_abandoned_visited_revisit())) { // try to swap in the visited list on NULL
@@ -974,19 +1158,21 @@ static mi_segment_t* mi_abandoned_pop(void) {
   // Do a pop. We use a reader count to prevent
   // a segment to be decommitted while a read is still pending,
   // and a tagged pointer to prevent A-B-A link corruption.
-  // (this is called from `memory.c:_mi_mem_free` for example)
-  mi_atomic_increment(&abandoned_readers);  // ensure no segment gets decommitted
+  // (this is called from `region.c:_mi_mem_free` for example)
+  mi_atomic_increment_relaxed(&abandoned_readers);  // ensure no segment gets decommitted
   mi_tagged_segment_t next = 0;
+  ts = mi_atomic_load_acquire(&abandoned);
   do {
-    ts = mi_atomic_read(&abandoned);
     segment = mi_tagged_segment_ptr(ts);
     if (segment != NULL) {
-      next = mi_tagged_segment(segment->abandoned_next, ts); // note: reads the segment's `abandoned_next` field so should not be decommitted
+      mi_segment_t* anext = mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next);
+      next = mi_tagged_segment(anext, ts); // note: reads the segment's `abandoned_next` field so should not be decommitted
     }
-  } while (segment != NULL && !mi_atomic_cas_weak(&abandoned, next, ts));
-  mi_atomic_decrement(&abandoned_readers);  // release reader lock
+  } while (segment != NULL && !mi_atomic_cas_weak_acq_rel(&abandoned, &ts, next));
+  mi_atomic_decrement_relaxed(&abandoned_readers);  // release reader lock
   if (segment != NULL) {
-    segment->abandoned_next = NULL;
+    mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL);
+    mi_atomic_decrement_relaxed(&abandoned_count);
   }
   return segment;
 }
@@ -998,21 +1184,32 @@ static mi_segment_t* mi_abandoned_pop(void) {
 static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) {
   mi_assert_internal(segment->used == segment->abandoned);
   mi_assert_internal(segment->used > 0);
-  mi_assert_internal(segment->abandoned_next == NULL);
-  mi_assert_expensive(mi_segment_is_valid(segment, tld));
-
-  // remove the segment from the free page queue if needed
-  mi_reset_delayed(tld);
-  mi_pages_reset_remove_all_in_segment(segment, mi_option_is_enabled(mi_option_abandoned_page_reset), tld);
-  mi_segment_remove_from_free_queue(segment, tld);
-  mi_assert_internal(segment->next == NULL && segment->prev == NULL);
+  mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL);
+  mi_assert_internal(segment->abandoned_visits == 0);
+  mi_assert_expensive(mi_segment_is_valid(segment,tld));
+  
+  // remove the free pages from the free page queues
+  mi_slice_t* slice = &segment->slices[0];
+  const mi_slice_t* end = mi_segment_slices_end(segment);
+  while (slice < end) {
+    mi_assert_internal(slice->slice_count > 0);
+    mi_assert_internal(slice->slice_offset == 0);
+    if (slice->xblock_size == 0) { // a free page
+      mi_segment_span_remove_from_queue(slice,tld);
+      slice->xblock_size = 0; // but keep it free
+    }
+    slice = slice + slice->slice_count;
+  }
 
+  // perform delayed decommits
+  mi_segment_delayed_decommit(segment, mi_option_is_enabled(mi_option_abandoned_page_decommit) /* force? */, tld->stats);    
+  
   // all pages in the segment are abandoned; add it to the abandoned list
   _mi_stat_increase(&tld->stats->segments_abandoned, 1);
-  mi_segments_track_size(-((long)segment->segment_size), tld);
+  mi_segments_track_size(-((long)mi_segment_size(segment)), tld);
   segment->thread_id = 0;
-  segment->abandoned_next = NULL;
-  segment->abandoned_visits = 0;
+  mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL);
+  segment->abandoned_visits = 1;   // from 0 to 1 to signify it is abandoned
   mi_abandoned_push(segment);
 }
 
@@ -1021,9 +1218,10 @@ void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) {
   mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE);
   mi_assert_internal(mi_page_heap(page) == NULL);
   mi_segment_t* segment = _mi_page_segment(page);
-  mi_assert_expensive(!mi_pages_reset_contains(page, tld));
-  mi_assert_expensive(mi_segment_is_valid(segment, tld));
-  segment->abandoned++;
+
+  mi_assert_expensive(mi_segment_is_valid(segment,tld));
+  segment->abandoned++;  
+
   _mi_stat_increase(&tld->stats->pages_abandoned, 1);
   mi_assert_internal(segment->abandoned <= segment->used);
   if (segment->used == segment->abandoned) {
@@ -1036,75 +1234,96 @@ void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld) {
   Reclaim abandoned pages
 ----------------------------------------------------------- */
 
-// Possibly clear pages and check if free space is available
-static bool mi_segment_check_free(mi_segment_t* segment, size_t block_size, bool* all_pages_free)
+static mi_slice_t* mi_slices_start_iterate(mi_segment_t* segment, const mi_slice_t** end) {
+  mi_slice_t* slice = &segment->slices[0];
+  *end = mi_segment_slices_end(segment);
+  mi_assert_internal(slice->slice_count>0 && slice->xblock_size>0); // segment allocated page
+  slice = slice + slice->slice_count; // skip the first segment allocated page
+  return slice;
+}
+
+// Possibly free pages and check if free space is available
+static bool mi_segment_check_free(mi_segment_t* segment, size_t slices_needed, size_t block_size, mi_segments_tld_t* tld) 
 {
   mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE);
+  mi_assert_internal(mi_segment_is_abandoned(segment));
   bool has_page = false;
-  size_t pages_used = 0;
-  size_t pages_used_empty = 0;
-  for (size_t i = 0; i < segment->capacity; i++) {
-    mi_page_t* page = &segment->pages[i];
-    if (page->segment_in_use) {
-      pages_used++;
+  
+  // for all slices
+  const mi_slice_t* end;
+  mi_slice_t* slice = mi_slices_start_iterate(segment, &end);
+  while (slice < end) {
+    mi_assert_internal(slice->slice_count > 0);
+    mi_assert_internal(slice->slice_offset == 0);
+    if (mi_slice_is_used(slice)) { // used page
       // ensure used count is up to date and collect potential concurrent frees
+      mi_page_t* const page = mi_slice_to_page(slice);
       _mi_page_free_collect(page, false);
       if (mi_page_all_free(page)) {
-        // if everything free already, page can be reused for some block size
-        // note: don't clear the page yet as we can only OS reset it once it is reclaimed
-        pages_used_empty++;
-        has_page = true;
-      }
-      else if (page->xblock_size == block_size && mi_page_has_any_available(page)) {
-        // a page has available free blocks of the right size
-        has_page = true;
+        // if this page is all free now, free it without adding to any queues (yet) 
+        mi_assert_internal(page->next == NULL && page->prev==NULL);
+        _mi_stat_decrease(&tld->stats->pages_abandoned, 1);
+        segment->abandoned--;
+        slice = mi_segment_page_clear(page, tld); // re-assign slice due to coalesce!
+        mi_assert_internal(!mi_slice_is_used(slice));
+        if (slice->slice_count >= slices_needed) {
+          has_page = true;
+        }
       }
+      else {
+        if (page->xblock_size == block_size && mi_page_has_any_available(page)) {
+          // a page has available free blocks of the right size
+          has_page = true;
+        }
+      }      
     }
     else {
-      // whole empty page
-      has_page = true;
+      // empty span
+      if (slice->slice_count >= slices_needed) {
+        has_page = true;
+      }
     }
-  }
-  mi_assert_internal(pages_used == segment->used && pages_used >= pages_used_empty);
-  if (all_pages_free != NULL) {
-    *all_pages_free = ((pages_used - pages_used_empty) == 0);
+    slice = slice + slice->slice_count;
   }
   return has_page;
 }
 
-
-// Reclaim a segment; returns NULL if the segment was freed
+// Reclaim an abandoned segment; returns NULL if the segment was freed
 // set `right_page_reclaimed` to `true` if it reclaimed a page of the right `block_size` that was not full.
 static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap, size_t requested_block_size, bool* right_page_reclaimed, mi_segments_tld_t* tld) {
-  mi_assert_internal(segment->abandoned_next == NULL);
+  mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_segment_t, &segment->abandoned_next) == NULL);
+  mi_assert_expensive(mi_segment_is_valid(segment, tld));
   if (right_page_reclaimed != NULL) { *right_page_reclaimed = false; }
 
   segment->thread_id = _mi_thread_id();
   segment->abandoned_visits = 0;
-  mi_segments_track_size((long)segment->segment_size, tld);
-  mi_assert_internal(segment->next == NULL && segment->prev == NULL);
-  mi_assert_expensive(mi_segment_is_valid(segment, tld));
+  mi_segments_track_size((long)mi_segment_size(segment), tld);
+  mi_assert_internal(segment->next == NULL);
   _mi_stat_decrease(&tld->stats->segments_abandoned, 1);
-
-  for (size_t i = 0; i < segment->capacity; i++) {
-    mi_page_t* page = &segment->pages[i];
-    if (page->segment_in_use) {
+  
+  // for all slices
+  const mi_slice_t* end;
+  mi_slice_t* slice = mi_slices_start_iterate(segment, &end);
+  while (slice < end) {
+    mi_assert_internal(slice->slice_count > 0);
+    mi_assert_internal(slice->slice_offset == 0);
+    if (mi_slice_is_used(slice)) {
+      // in use: reclaim the page in our heap
+      mi_page_t* page = mi_slice_to_page(slice);
       mi_assert_internal(!page->is_reset);
       mi_assert_internal(page->is_committed);
-      mi_assert_internal(mi_page_not_in_queue(page, tld));
       mi_assert_internal(mi_page_thread_free_flag(page)==MI_NEVER_DELAYED_FREE);
       mi_assert_internal(mi_page_heap(page) == NULL);
-      segment->abandoned--;
-      mi_assert(page->next == NULL);
+      mi_assert_internal(page->next == NULL && page->prev==NULL);
       _mi_stat_decrease(&tld->stats->pages_abandoned, 1);
-      // set the heap again and allow heap thread delayed free again.
+      segment->abandoned--;
+      // set the heap again and allow delayed free again
       mi_page_set_heap(page, heap);
       _mi_page_use_delayed_free(page, MI_USE_DELAYED_FREE, true); // override never (after heap is set)
-      // TODO: should we not collect again given that we just collected in `check_free`?
       _mi_page_free_collect(page, false); // ensure used count is up to date
       if (mi_page_all_free(page)) {
-        // if everything free already, clear the page directly
-        mi_segment_page_clear(segment, page, true, tld);  // reset is ok now
+        // if everything free by now, free the page
+        slice = mi_segment_page_clear(page, tld);   // set slice again due to coalesceing
       }
       else {
         // otherwise reclaim it into the heap
@@ -1114,21 +1333,21 @@ static mi_segment_t* mi_segment_reclaim(mi_segment_t* segment, mi_heap_t* heap,
         }
       }
     }
-    else if (page->is_committed && !page->is_reset) {  // not in-use, and not reset yet
-      // note: do not reset as this includes pages that were not touched before
-      // mi_pages_reset_add(segment, page, tld);
+    else {
+      // the span is free, add it to our page queues
+      slice = mi_segment_span_free_coalesce(slice, tld); // set slice again due to coalesceing
     }
+    mi_assert_internal(slice->slice_count>0 && slice->slice_offset==0);
+    slice = slice + slice->slice_count;
   }
-  mi_assert_internal(segment->abandoned == 0);
-  if (segment->used == 0) {
+
+  mi_assert(segment->abandoned == 0);
+  if (segment->used == 0) {  // due to page_clear
     mi_assert_internal(right_page_reclaimed == NULL || !(*right_page_reclaimed));
     mi_segment_free(segment, false, tld);
     return NULL;
   }
   else {
-    if (segment->page_kind <= MI_PAGE_MEDIUM && mi_segment_has_free(segment)) {
-      mi_segment_insert_in_free_queue(segment, tld);
-    }
     return segment;
   }
 }
@@ -1141,16 +1360,15 @@ void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld) {
   }
 }
 
-static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, bool* reclaimed, mi_segments_tld_t* tld)
+static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t needed_slices, size_t block_size, bool* reclaimed, mi_segments_tld_t* tld)
 {
   *reclaimed = false;
   mi_segment_t* segment;
-  int max_tries = 8;     // limit the work to bound allocation times
+  long max_tries = mi_option_get_clamp(mi_option_max_segment_reclaim, 8, 1024);     // limit the work to bound allocation times  
   while ((max_tries-- > 0) && ((segment = mi_abandoned_pop()) != NULL)) {
     segment->abandoned_visits++;
-    bool all_pages_free;
-    bool has_page = mi_segment_check_free(segment,block_size,&all_pages_free); // try to free up pages (due to concurrent frees)
-    if (all_pages_free) {
+    bool has_page = mi_segment_check_free(segment,needed_slices,block_size,tld); // try to free up pages (due to concurrent frees)
+    if (segment->used == 0) {
       // free the segment (by forced reclaim) to make it available to other threads.
       // note1: we prefer to free a segment as that might lead to reclaiming another
       // segment that is still partially used.
@@ -1158,18 +1376,19 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size,
       // freeing but that would violate some invariants temporarily)
       mi_segment_reclaim(segment, heap, 0, NULL, tld);
     }
-    else if (has_page && segment->page_kind == page_kind) {
-      // found a free page of the right kind, or page of the right block_size with free space
+    else if (has_page) {
+      // found a large enough free span, or a page of the right block_size with free space 
       // we return the result of reclaim (which is usually `segment`) as it might free
       // the segment due to concurrent frees (in which case `NULL` is returned).
       return mi_segment_reclaim(segment, heap, block_size, reclaimed, tld);
     }
-    else if (segment->abandoned_visits >= 3) {
-      // always reclaim on 3rd visit to limit the list length.
+    else if (segment->abandoned_visits > 3) {  
+      // always reclaim on 3rd visit to limit the abandoned queue length.
       mi_segment_reclaim(segment, heap, 0, NULL, tld);
     }
     else {
       // otherwise, push on the visited list so it gets not looked at too quickly again
+      mi_segment_delayed_decommit(segment, true /* force? */, tld->stats); // forced decommit if needed as we may not visit soon again
       mi_abandoned_visited_push(segment);
     }
   }
@@ -1177,167 +1396,149 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size,
 }
 
 
+void _mi_abandoned_collect(mi_heap_t* heap, bool force, mi_segments_tld_t* tld)
+{
+  mi_segment_t* segment;
+  int max_tries = (force ? 16*1024 : 1024); // limit latency
+  if (force) {
+    mi_abandoned_visited_revisit(); 
+  }
+  while ((max_tries-- > 0) && ((segment = mi_abandoned_pop()) != NULL)) {
+    mi_segment_check_free(segment,0,0,tld); // try to free up pages (due to concurrent frees)
+    if (segment->used == 0) {
+      // free the segment (by forced reclaim) to make it available to other threads.
+      // note: we could in principle optimize this by skipping reclaim and directly
+      // freeing but that would violate some invariants temporarily)
+      mi_segment_reclaim(segment, heap, 0, NULL, tld);
+    }
+    else {
+      // otherwise, decommit if needed and push on the visited list 
+      // note: forced decommit can be expensive if many threads are destroyed/created as in mstress.
+      mi_segment_delayed_decommit(segment, force, tld->stats);
+      mi_abandoned_visited_push(segment);
+    }
+  }
+}
+
 /* -----------------------------------------------------------
    Reclaim or allocate
 ----------------------------------------------------------- */
 
-static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t page_kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
+static mi_segment_t* mi_segment_reclaim_or_alloc(mi_heap_t* heap, size_t needed_slices, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) 
 {
-  mi_assert_internal(page_kind <= MI_PAGE_LARGE);
   mi_assert_internal(block_size < MI_HUGE_BLOCK_SIZE);
-  // 1. try to get a segment from our cache
-  mi_segment_t* segment = mi_segment_cache_pop(MI_SEGMENT_SIZE, tld);
-  if (segment != NULL) {
-    mi_segment_init(segment, 0, page_kind, page_shift, tld, os_tld);
-    return segment;
-  }
-  // 2. try to reclaim an abandoned segment
+  mi_assert_internal(block_size <= MI_LARGE_OBJ_SIZE_MAX);
+  
+  // 1. try to reclaim an abandoned segment
   bool reclaimed;
-  segment = mi_segment_try_reclaim(heap, block_size, page_kind, &reclaimed, tld);
+  mi_segment_t* segment = mi_segment_try_reclaim(heap, needed_slices, block_size, &reclaimed, tld);
   if (reclaimed) {
     // reclaimed the right page right into the heap
-    mi_assert_internal(segment != NULL && segment->page_kind == page_kind && page_kind <= MI_PAGE_LARGE);
+    mi_assert_internal(segment != NULL);
     return NULL; // pretend out-of-memory as the page will be in the page queue of the heap with available blocks
   }
   else if (segment != NULL) {
-    // reclaimed a segment with empty pages (of `page_kind`) in it
+    // reclaimed a segment with a large enough empty span in it
     return segment;
   }
-  // 3. otherwise allocate a fresh segment
-  return mi_segment_alloc(0, page_kind, page_shift, tld, os_tld);
+  // 2. otherwise allocate a fresh segment
+  return mi_segment_alloc(0, tld, os_tld, NULL);  
 }
 
 
 /* -----------------------------------------------------------
-   Small page allocation
+   Page allocation
 ----------------------------------------------------------- */
 
-static mi_page_t* mi_segment_find_free(mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_assert_internal(mi_segment_has_free(segment));
-  mi_assert_expensive(mi_segment_is_valid(segment, tld));
-  for (size_t i = 0; i < segment->capacity; i++) {  // TODO: use a bitmap instead of search?
-    mi_page_t* page = &segment->pages[i];
-    if (!page->segment_in_use) {
-      bool ok = mi_segment_page_claim(segment, page, tld);
-      if (ok) return page;
+static mi_page_t* mi_segments_page_alloc(mi_heap_t* heap, mi_page_kind_t page_kind, size_t required, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
+{
+  mi_assert_internal(required <= MI_LARGE_OBJ_SIZE_MAX && page_kind <= MI_PAGE_LARGE);
+
+  // find a free page
+  size_t page_size = _mi_align_up(required, (required > MI_MEDIUM_PAGE_SIZE ? MI_MEDIUM_PAGE_SIZE : MI_SEGMENT_SLICE_SIZE));
+  size_t slices_needed = page_size / MI_SEGMENT_SLICE_SIZE;
+  mi_assert_internal(slices_needed * MI_SEGMENT_SLICE_SIZE == page_size);
+  mi_page_t* page = mi_segments_page_find_and_allocate(slices_needed, tld); //(required <= MI_SMALL_SIZE_MAX ? 0 : slices_needed), tld);
+  if (page==NULL) {
+    // no free page, allocate a new segment and try again
+    if (mi_segment_reclaim_or_alloc(heap, slices_needed, block_size, tld, os_tld) == NULL) {
+      // OOM or reclaimed a good page in the heap
+      return NULL;  
+    }
+    else {
+      // otherwise try again
+      return mi_segments_page_alloc(heap, page_kind, required, block_size, tld, os_tld);
     }
   }
-  mi_assert(false);
-  return NULL;
-}
-
-// Allocate a page inside a segment. Requires that the page has free pages
-static mi_page_t* mi_segment_page_alloc_in(mi_segment_t* segment, mi_segments_tld_t* tld) {
-  mi_assert_internal(mi_segment_has_free(segment));
-  return mi_segment_find_free(segment, tld);
-}
-
-static mi_page_t* mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_page_kind_t kind, size_t page_shift, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
-  // find an available segment the segment free queue
-  mi_segment_queue_t* const free_queue = mi_segment_free_queue_of_kind(kind, tld);
-  if (mi_segment_queue_is_empty(free_queue)) {
-    // possibly allocate or reclaim a fresh segment
-    mi_segment_t* const segment = mi_segment_reclaim_or_alloc(heap, block_size, kind, page_shift, tld, os_tld);
-    if (segment == NULL) return NULL;  // return NULL if out-of-memory (or reclaimed)
-    mi_assert_internal(free_queue->first == segment);
-    mi_assert_internal(segment->page_kind==kind);
-    mi_assert_internal(segment->used < segment->capacity);
-  }
-  mi_assert_internal(free_queue->first != NULL);
-  mi_page_t* const page = mi_segment_page_alloc_in(free_queue->first, tld);
-  mi_assert_internal(page != NULL);
-#if MI_DEBUG>=2
-  // verify it is committed
-  _mi_segment_page_start(_mi_page_segment(page), page, sizeof(void*), NULL, NULL)[0] = 0;
-#endif
+  mi_assert_internal(page != NULL && page->slice_count*MI_SEGMENT_SLICE_SIZE == page_size);
+  mi_assert_internal(_mi_ptr_segment(page)->thread_id == _mi_thread_id());
+  mi_segment_delayed_decommit(_mi_ptr_segment(page), false, tld->stats);
   return page;
 }
 
-static mi_page_t* mi_segment_small_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
-  return mi_segment_page_alloc(heap, block_size, MI_PAGE_SMALL,MI_SMALL_PAGE_SHIFT,tld,os_tld);
-}
 
-static mi_page_t* mi_segment_medium_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
-  return mi_segment_page_alloc(heap, block_size, MI_PAGE_MEDIUM, MI_MEDIUM_PAGE_SHIFT, tld, os_tld);
-}
 
 /* -----------------------------------------------------------
-   large page allocation
+   Huge page allocation
 ----------------------------------------------------------- */
 
-static mi_page_t* mi_segment_large_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
-  mi_segment_t* segment = mi_segment_reclaim_or_alloc(heap,block_size,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld);
-  if (segment == NULL) return NULL;
-  mi_page_t* page = mi_segment_find_free(segment, tld);
-  mi_assert_internal(page != NULL);
-#if MI_DEBUG>=2
-  _mi_segment_page_start(segment, page, sizeof(void*), NULL, NULL)[0] = 0;
-#endif
-  return page;
-}
-
 static mi_page_t* mi_segment_huge_page_alloc(size_t size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
 {
-  mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT,tld,os_tld);
-  if (segment == NULL) return NULL;
-  mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size);
-  segment->thread_id = 0; // huge pages are immediately abandoned
-  mi_segments_track_size(-(long)segment->segment_size, tld);
-  mi_page_t* page = mi_segment_find_free(segment, tld);
-  mi_assert_internal(page != NULL);
+  mi_page_t* page = NULL;
+  mi_segment_t* segment = mi_segment_alloc(size,tld,os_tld,&page);
+  if (segment == NULL || page==NULL) return NULL;
+  mi_assert_internal(segment->used==1);
+  mi_assert_internal(mi_page_block_size(page) >= size);  
+  segment->thread_id = 0; // huge segments are immediately abandoned
   return page;
 }
 
 // free huge block from another thread
 void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block) {
   // huge page segments are always abandoned and can be freed immediately by any thread
-  mi_assert_internal(segment->page_kind==MI_PAGE_HUGE);
+  mi_assert_internal(segment->kind==MI_SEGMENT_HUGE);
   mi_assert_internal(segment == _mi_page_segment(page));
-  mi_assert_internal(mi_atomic_read_relaxed(&segment->thread_id)==0);
+  mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id)==0);
 
   // claim it and free
   mi_heap_t* heap = mi_heap_get_default(); // issue #221; don't use the internal get_default_heap as we need to ensure the thread is initialized.
   // paranoia: if this it the last reference, the cas should always succeed
-  if (mi_atomic_cas_strong(&segment->thread_id, heap->thread_id, 0)) {
+  size_t expected_tid = 0;
+  if (mi_atomic_cas_strong_acq_rel(&segment->thread_id, &expected_tid, heap->thread_id)) {
     mi_block_set_next(page, block, page->free);
     page->free = block;
     page->used--;
     page->is_zero = false;
     mi_assert(page->used == 0);
     mi_tld_t* tld = heap->tld;
-    const size_t bsize = mi_page_usable_block_size(page);
-    if (bsize > MI_HUGE_OBJ_SIZE_MAX) {
-      _mi_stat_decrease(&tld->stats.giant, bsize); 
-    }
-    else {
-      _mi_stat_decrease(&tld->stats.huge, bsize);
-    }
-    mi_segments_track_size((long)segment->segment_size, &tld->segments);
     _mi_segment_page_free(page, true, &tld->segments);
   }
+#if (MI_DEBUG!=0)
+  else {
+    mi_assert_internal(false);
+  }
+#endif
 }
 
 /* -----------------------------------------------------------
-   Page allocation
+   Page allocation and free
 ----------------------------------------------------------- */
-
 mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
   mi_page_t* page;
   if (block_size <= MI_SMALL_OBJ_SIZE_MAX) {
-    page = mi_segment_small_page_alloc(heap, block_size, tld, os_tld);
+    page = mi_segments_page_alloc(heap,MI_PAGE_SMALL,block_size,block_size,tld,os_tld);
   }
   else if (block_size <= MI_MEDIUM_OBJ_SIZE_MAX) {
-    page = mi_segment_medium_page_alloc(heap, block_size, tld, os_tld);
+    page = mi_segments_page_alloc(heap,MI_PAGE_MEDIUM,MI_MEDIUM_PAGE_SIZE,block_size,tld, os_tld);
   }
   else if (block_size <= MI_LARGE_OBJ_SIZE_MAX) {
-    page = mi_segment_large_page_alloc(heap, block_size, tld, os_tld);
+    page = mi_segments_page_alloc(heap,MI_PAGE_LARGE,block_size,block_size,tld, os_tld);
   }
   else {
     page = mi_segment_huge_page_alloc(block_size,tld,os_tld);
   }
   mi_assert_expensive(page == NULL || mi_segment_is_valid(_mi_page_segment(page),tld));
-  mi_assert_internal(page == NULL || (mi_segment_page_size(_mi_page_segment(page)) - (MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= block_size);
-  mi_reset_delayed(tld);
-  mi_assert_internal(page == NULL || mi_page_not_in_queue(page, tld));
   return page;
 }
+
+
index d024b01a98c41f8ee7b05b594fd8f97e4803caf9..5b34ddbb6ce0ba2fd5556e31aadecc538a8d73a0 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -23,8 +23,9 @@ terms of the MIT license. A copy of the license can be found in the file
 #include "stats.c"
 #include "random.c"
 #include "os.c"
+#include "bitmap.c"
 #include "arena.c"
-#include "region.c"
+#include "segment-cache.c"
 #include "segment.c"
 #include "page.c"
 #include "heap.c"
index 203bad81647125104dcded7ad0d84c73dbbac8a6..134a7bcb6b9775fc9b13ede30e30f4f959032b40 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
@@ -11,6 +11,9 @@ terms of the MIT license. A copy of the license can be found in the file
 #include <stdio.h>  // fputs, stderr
 #include <string.h> // memset
 
+#if defined(_MSC_VER) && (_MSC_VER < 1920)
+#pragma warning(disable:4204)  // non-constant aggregate initializer
+#endif
 
 /* -----------------------------------------------------------
   Statistics operations
@@ -26,13 +29,13 @@ static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) {
   if (mi_is_in_main(stat))
   {
     // add atomically (for abandoned pages)
-    mi_atomic_addi64(&stat->current,amount);
-    mi_atomic_maxi64(&stat->peak, mi_atomic_readi64(&stat->current));
+    int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount);
+    mi_atomic_maxi64_relaxed(&stat->peak, current + amount);
     if (amount > 0) {
-      mi_atomic_addi64(&stat->allocated,amount);
+      mi_atomic_addi64_relaxed(&stat->allocated,amount);
     }
     else {
-      mi_atomic_addi64(&stat->freed, -amount);
+      mi_atomic_addi64_relaxed(&stat->freed, -amount);
     }
   }
   else {
@@ -50,8 +53,8 @@ static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) {
 
 void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) {  
   if (mi_is_in_main(stat)) {
-    mi_atomic_addi64( &stat->count, 1 );
-    mi_atomic_addi64( &stat->total, (int64_t)amount );
+    mi_atomic_addi64_relaxed( &stat->count, 1 );
+    mi_atomic_addi64_relaxed( &stat->total, (int64_t)amount );
   }
   else {
     stat->count++;
@@ -71,17 +74,17 @@ void _mi_stat_decrease(mi_stat_count_t* stat, size_t amount) {
 static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) {
   if (stat==src) return;
   if (src->allocated==0 && src->freed==0) return;
-  mi_atomic_addi64( &stat->allocated, src->allocated * unit);
-  mi_atomic_addi64( &stat->current, src->current * unit);
-  mi_atomic_addi64( &stat->freed, src->freed * unit);
-  // peak scores do not work across threads..
-  mi_atomic_addi64( &stat->peak, src->peak * unit);
+  mi_atomic_addi64_relaxed( &stat->allocated, src->allocated * unit);
+  mi_atomic_addi64_relaxed( &stat->current, src->current * unit);
+  mi_atomic_addi64_relaxed( &stat->freed, src->freed * unit);
+  // peak scores do not work across threads.. 
+  mi_atomic_addi64_relaxed( &stat->peak, src->peak * unit);
 }
 
 static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src, int64_t unit) {
   if (stat==src) return;
-  mi_atomic_addi64( &stat->total, src->total * unit);
-  mi_atomic_addi64( &stat->count, src->count * unit);
+  mi_atomic_addi64_relaxed( &stat->total, src->total * unit);
+  mi_atomic_addi64_relaxed( &stat->count, src->count * unit);
 }
 
 // must be thread safe as it is called from stats_merge
@@ -100,8 +103,9 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
 
   mi_stat_add(&stats->malloc, &src->malloc, 1);
   mi_stat_add(&stats->segments_cache, &src->segments_cache, 1);
+  mi_stat_add(&stats->normal, &src->normal, 1);
   mi_stat_add(&stats->huge, &src->huge, 1);
-  mi_stat_add(&stats->giant, &src->giant, 1);
+  mi_stat_add(&stats->large, &src->large, 1);
 
   mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1);
   mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls, 1);
@@ -109,12 +113,13 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
 
   mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire, 1);
   mi_stat_counter_add(&stats->searches, &src->searches, 1);
+  mi_stat_counter_add(&stats->normal_count, &src->normal_count, 1);
   mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1);
-  mi_stat_counter_add(&stats->giant_count, &src->giant_count, 1);
+  mi_stat_counter_add(&stats->large_count, &src->large_count, 1);
 #if MI_STAT>1
   for (size_t i = 0; i <= MI_BIN_HUGE; i++) {
-    if (src->normal[i].allocated > 0 || src->normal[i].freed > 0) {
-      mi_stat_add(&stats->normal[i], &src->normal[i], 1);
+    if (src->normal_bins[i].allocated > 0 || src->normal_bins[i].freed > 0) {
+      mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i], 1);
     }
   }
 #endif
@@ -128,25 +133,29 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
 // unit == 0: count as decimal
 // unit < 0 : count in binary
 static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void* arg, const char* fmt) {
-  char buf[32];
+  char buf[32]; buf[0] = 0;  
   int  len = 32;
-  const char* suffix = (unit <= 0 ? " " : "b");
+  const char* suffix = (unit <= 0 ? " " : "B");
   const int64_t base = (unit == 0 ? 1000 : 1024);
   if (unit>0) n *= unit;
 
   const int64_t pos = (n < 0 ? -n : n);
   if (pos < base) {
-    snprintf(buf, len, "%d %s ", (int)n, suffix);
+    if (n!=1 || suffix[0] != 'B') {  // skip printing 1 B for the unit column
+      snprintf(buf, len, "%d %-3s", (int)n, (n==0 ? "" : suffix));
+    }
   }
   else {
-    int64_t divider = base;
-    const char* magnitude = "k";
-    if (pos >= divider*base) { divider *= base; magnitude = "m"; }
-    if (pos >= divider*base) { divider *= base; magnitude = "g"; }
+    int64_t divider = base;    
+    const char* magnitude = "K";
+    if (pos >= divider*base) { divider *= base; magnitude = "M"; }
+    if (pos >= divider*base) { divider *= base; magnitude = "G"; }
     const int64_t tens = (n / (divider/10));
     const long whole = (long)(tens/10);
     const long frac1 = (long)(tens%10);
-    snprintf(buf, len, "%ld.%ld %s%s", whole, frac1, magnitude, suffix);
+    char unitdesc[8];
+    snprintf(unitdesc, 8, "%s%s%s", magnitude, (base==1024 ? "i" : ""), suffix);
+    snprintf(buf, len, "%ld.%ld %-3s", whole, (frac1 < 0 ? -frac1 : frac1), unitdesc);
   }
   _mi_fprintf(out, arg, (fmt==NULL ? "%11s" : fmt), buf);
 }
@@ -167,6 +176,7 @@ static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t
     mi_print_amount(stat->peak, unit, out, arg);
     mi_print_amount(stat->allocated, unit, out, arg);
     mi_print_amount(stat->freed, unit, out, arg);
+    mi_print_amount(stat->current, unit, out, arg);
     mi_print_amount(unit, 1, out, arg);
     mi_print_count(stat->allocated, unit, out, arg);
     if (stat->allocated > stat->freed)
@@ -178,6 +188,7 @@ static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t
     mi_print_amount(stat->peak, -1, out, arg);
     mi_print_amount(stat->allocated, -1, out, arg);
     mi_print_amount(stat->freed, -1, out, arg);
+    mi_print_amount(stat->current, -1, out, arg);
     if (unit==-1) {
       _mi_fprintf(out, arg, "%22s", "");
     }
@@ -193,6 +204,8 @@ static void mi_stat_print(const mi_stat_count_t* stat, const char* msg, int64_t
   else {
     mi_print_amount(stat->peak, 1, out, arg);
     mi_print_amount(stat->allocated, 1, out, arg);
+    _mi_fprintf(out, arg, "%11s", " ");  // no freed 
+    mi_print_amount(stat->current, 1, out, arg);
     _mi_fprintf(out, arg, "\n");
   }
 }
@@ -212,24 +225,21 @@ static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char*
 
 
 static void mi_print_header(mi_output_fun* out, void* arg ) {
-  _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s\n", "heap stats", "peak  ", "total  ", "freed  ", "unit  ", "count  ");
+  _mi_fprintf(out, arg, "%10s: %10s %10s %10s %10s %10s %10s\n", "heap stats", "peak   ", "total   ", "freed   ", "current   ", "unit   ", "count   ");
 }
 
 #if MI_STAT>1
-static void mi_stats_print_bins(mi_stat_count_t* all, const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out, void* arg) {
+static void mi_stats_print_bins(const mi_stat_count_t* bins, size_t max, const char* fmt, mi_output_fun* out, void* arg) {
   bool found = false;
   char buf[64];
   for (size_t i = 0; i <= max; i++) {
     if (bins[i].allocated > 0) {
       found = true;
       int64_t unit = _mi_bin_size((uint8_t)i);
-      snprintf(buf, 64, "%s %3zu", fmt, i);
-      mi_stat_add(all, &bins[i], unit);
+      snprintf(buf, 64, "%s %3lu", fmt, (long)i);
       mi_stat_print(&bins[i], buf, unit, out, arg);
     }
   }
-  //snprintf(buf, 64, "%s all", fmt);
-  //mi_stat_print(all, buf, 1);
   if (found) {
     _mi_fprintf(out, arg, "\n");
     mi_print_header(out, arg);
@@ -273,31 +283,34 @@ static void mi_buffered_out(const char* msg, void* arg) {
 // Print statistics
 //------------------------------------------------------------
 
-static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit);
+static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults);
 
-static void _mi_stats_print(mi_stats_t* stats, mi_msecs_t elapsed, mi_output_fun* out0, void* arg0) mi_attr_noexcept {
+static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept {
   // wrap the output function to be line buffered
   char buf[256];
-  buffered_t buffer = { out0, arg0, buf, 0, 255 };
+  buffered_t buffer = { out0, arg0, NULL, 0, 255 };
+  buffer.buf = buf;
   mi_output_fun* out = &mi_buffered_out;
   void* arg = &buffer;
 
   // and print using that
   mi_print_header(out,arg);
   #if MI_STAT>1
-  mi_stat_count_t normal = { 0,0,0,0 };
-  mi_stats_print_bins(&normal, stats->normal, MI_BIN_HUGE, "normal",out,arg);
-  mi_stat_print(&normal, "normal", 1, out, arg);
+  mi_stats_print_bins(stats->normal_bins, MI_BIN_HUGE, "normal",out,arg);
+  #endif
+  #if MI_STAT
+  mi_stat_print(&stats->normal, "normal", (stats->normal_count.count == 0 ? 1 : -(stats->normal.allocated / stats->normal_count.count)), out, arg);
+  mi_stat_print(&stats->large, "large", (stats->large_count.count == 0 ? 1 : -(stats->large.allocated / stats->large_count.count)), out, arg);
   mi_stat_print(&stats->huge, "huge", (stats->huge_count.count == 0 ? 1 : -(stats->huge.allocated / stats->huge_count.count)), out, arg);
-  mi_stat_print(&stats->giant, "giant", (stats->giant_count.count == 0 ? 1 : -(stats->giant.allocated / stats->giant_count.count)), out, arg);
   mi_stat_count_t total = { 0,0,0,0 };
-  mi_stat_add(&total, &normal, 1);
+  mi_stat_add(&total, &stats->normal, 1);
+  mi_stat_add(&total, &stats->large, 1);
   mi_stat_add(&total, &stats->huge, 1);
-  mi_stat_add(&total, &stats->giant, 1);
   mi_stat_print(&total, "total", 1, out, arg);
-  _mi_fprintf(out, arg, "malloc requested:     ");
-  mi_print_amount(stats->malloc.allocated, 1, out, arg);
-  _mi_fprintf(out, arg, "\n\n");
+  #endif
+  #if MI_STAT>1
+  mi_stat_print(&stats->malloc, "malloc req", 1, out, arg);
+  _mi_fprintf(out, arg, "\n");
   #endif
   mi_stat_print(&stats->reserved, "reserved", 1, out, arg);
   mi_stat_print(&stats->committed, "committed", 1, out, arg);
@@ -314,26 +327,29 @@ static void _mi_stats_print(mi_stats_t* stats, mi_msecs_t elapsed, mi_output_fun
   mi_stat_counter_print(&stats->commit_calls, "commits", out, arg);
   mi_stat_print(&stats->threads, "threads", -1, out, arg);
   mi_stat_counter_print_avg(&stats->searches, "searches", out, arg);
-  _mi_fprintf(out, arg, "%10s: %7i\n", "numa nodes", _mi_os_numa_node_count());
-  if (elapsed > 0) _mi_fprintf(out, arg, "%10s: %7ld.%03ld s\n", "elapsed", elapsed/1000, elapsed%1000);
-
+  _mi_fprintf(out, arg, "%10s: %7zu\n", "numa nodes", _mi_os_numa_node_count());
+  
+  mi_msecs_t elapsed;
   mi_msecs_t user_time;
   mi_msecs_t sys_time;
+  size_t current_rss;
   size_t peak_rss;
-  size_t page_faults;
-  size_t page_reclaim;
+  size_t current_commit;
   size_t peak_commit;
-  mi_process_info(&user_time, &sys_time, &peak_rss, &page_faults, &page_reclaim, &peak_commit);
-  _mi_fprintf(out, arg, "%10s: user: %ld.%03ld s, system: %ld.%03ld s, faults: %lu, reclaims: %lu, rss: ", "process", user_time/1000, user_time%1000, sys_time/1000, sys_time%1000, (unsigned long)page_faults, (unsigned long)page_reclaim );
+  size_t page_faults;
+  mi_stat_process_info(&elapsed, &user_time, &sys_time, &current_rss, &peak_rss, &current_commit, &peak_commit, &page_faults);
+  _mi_fprintf(out, arg, "%10s: %7ld.%03ld s\n", "elapsed", elapsed/1000, elapsed%1000);
+  _mi_fprintf(out, arg, "%10s: user: %ld.%03ld s, system: %ld.%03ld s, faults: %lu, rss: ", "process",
+              user_time/1000, user_time%1000, sys_time/1000, sys_time%1000, (unsigned long)page_faults );
   mi_printf_amount((int64_t)peak_rss, 1, out, arg, "%s");
   if (peak_commit > 0) {
-    _mi_fprintf(out, arg, ", commit charge: ");
+    _mi_fprintf(out, arg, ", commit: ");
     mi_printf_amount((int64_t)peak_commit, 1, out, arg, "%s");
   }
   _mi_fprintf(out, arg, "\n");  
 }
 
-static mi_msecs_t mi_time_start; // = 0
+static mi_msecs_t mi_process_start; // = 0
 
 static mi_stats_t* mi_stats_get_default(void) {
   mi_heap_t* heap = mi_heap_get_default();
@@ -351,7 +367,7 @@ void mi_stats_reset(void) mi_attr_noexcept {
   mi_stats_t* stats = mi_stats_get_default();
   if (stats != &_mi_stats_main) { memset(stats, 0, sizeof(mi_stats_t)); }
   memset(&_mi_stats_main, 0, sizeof(mi_stats_t));
-  mi_time_start = _mi_clock_start();
+  if (mi_process_start == 0) { mi_process_start = _mi_clock_start(); };
 }
 
 void mi_stats_merge(void) mi_attr_noexcept {
@@ -363,9 +379,8 @@ void _mi_stats_done(mi_stats_t* stats) {  // called from `mi_thread_done`
 }
 
 void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept {
-  mi_msecs_t elapsed = _mi_clock_end(mi_time_start);
   mi_stats_merge_from(mi_stats_get_default());
-  _mi_stats_print(&_mi_stats_main, elapsed, out, arg);
+  _mi_stats_print(&_mi_stats_main, out, arg);
 }
 
 void mi_stats_print(void* out) mi_attr_noexcept {
@@ -374,8 +389,7 @@ void mi_stats_print(void* out) mi_attr_noexcept {
 }
 
 void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept {
-  mi_msecs_t elapsed = _mi_clock_end(mi_time_start);
-  _mi_stats_print(mi_stats_get_default(), elapsed, out, arg);
+  _mi_stats_print(mi_stats_get_default(), out, arg);
 }
 
 
@@ -402,10 +416,14 @@ mi_msecs_t _mi_clock_now(void) {
 }
 #else
 #include <time.h>
-#ifdef CLOCK_REALTIME
+#if defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC)
 mi_msecs_t _mi_clock_now(void) {
   struct timespec t;
+  #ifdef CLOCK_MONOTONIC
+  clock_gettime(CLOCK_MONOTONIC, &t);
+  #else  
   clock_gettime(CLOCK_REALTIME, &t);
+  #endif
   return ((mi_msecs_t)t.tv_sec * 1000) + ((mi_msecs_t)t.tv_nsec / 1000000);
 }
 #else
@@ -449,7 +467,10 @@ static mi_msecs_t filetime_msecs(const FILETIME* ftime) {
   mi_msecs_t msecs = (i.QuadPart / 10000); // FILETIME is in 100 nano seconds
   return msecs;
 }
-static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit) {
+
+static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) 
+{
+  *elapsed = _mi_clock_end(mi_process_start);
   FILETIME ct;
   FILETIME ut;
   FILETIME st;
@@ -457,21 +478,21 @@ static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_r
   GetProcessTimes(GetCurrentProcess(), &ct, &et, &st, &ut);
   *utime = filetime_msecs(&ut);
   *stime = filetime_msecs(&st);
-
   PROCESS_MEMORY_COUNTERS info;
   GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
-  *peak_rss = (size_t)info.PeakWorkingSetSize;
-  *page_faults = (size_t)info.PageFaultCount;
-  *peak_commit = (size_t)info.PeakPagefileUsage;
-  *page_reclaim = 0;
+  *current_rss    = (size_t)info.WorkingSetSize;
+  *peak_rss       = (size_t)info.PeakWorkingSetSize;
+  *current_commit = (size_t)info.PagefileUsage;
+  *peak_commit    = (size_t)info.PeakPagefileUsage;
+  *page_faults    = (size_t)info.PageFaultCount;  
 }
 
-#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
+#elif !defined(__wasi__) && (defined(__unix__) || defined(__unix) || defined(unix) || defined(__APPLE__) || defined(__HAIKU__))
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/resource.h>
 
-#if defined(__APPLE__) && defined(__MACH__)
+#if defined(__APPLE__)
 #include <mach/mach.h>
 #endif
 
@@ -483,36 +504,41 @@ static mi_msecs_t timeval_secs(const struct timeval* tv) {
   return ((mi_msecs_t)tv->tv_sec * 1000L) + ((mi_msecs_t)tv->tv_usec / 1000L);
 }
 
-static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit) {
+static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults)
+{
+  *elapsed = _mi_clock_end(mi_process_start);
   struct rusage rusage;
   getrusage(RUSAGE_SELF, &rusage);
+  *utime = timeval_secs(&rusage.ru_utime);
+  *stime = timeval_secs(&rusage.ru_stime);
 #if !defined(__HAIKU__)
-#if defined(__APPLE__) && defined(__MACH__)
-  *peak_rss = rusage.ru_maxrss;
-#else
-  *peak_rss = rusage.ru_maxrss * 1024;
-#endif
   *page_faults = rusage.ru_majflt;
-  *page_reclaim = rusage.ru_minflt;
-  *peak_commit = 0;
-#else
-// Haiku does not have (yet?) a way to
-// get these stats per process
+#endif
+  // estimate commit using our stats
+  *peak_commit    = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak));
+  *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current));
+  *current_rss    = *current_commit;  // estimate 
+#if defined(__HAIKU__)
+  // Haiku does not have (yet?) a way to
+  // get these stats per process
   thread_info tid;
   area_info mem;
   ssize_t c;
-  *peak_rss = 0;
-  *page_faults = 0;
-  *page_reclaim = 0;
-  *peak_commit = 0;
   get_thread_info(find_thread(0), &tid);
-
   while (get_next_area_info(tid.team, &c, &mem) == B_OK) {
-      *peak_rss += mem.ram_size;
+    *peak_rss += mem.ram_size;
   }
-#endif
-  *utime = timeval_secs(&rusage.ru_utime);
-  *stime = timeval_secs(&rusage.ru_stime);
+  *page_faults = 0;
+#elif defined(__APPLE__)
+  *peak_rss = rusage.ru_maxrss;         // BSD reports in bytes
+  struct mach_task_basic_info info;
+  mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
+  if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &infoCount) == KERN_SUCCESS) {
+    *current_rss = (size_t)info.resident_size;
+  }
+#else
+  *peak_rss = rusage.ru_maxrss * 1024;  // Linux reports in KiB
+#endif  
 }
 
 #else
@@ -521,12 +547,38 @@ static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_r
 #pragma message("define a way to get process info")
 #endif
 
-static void mi_process_info(mi_msecs_t* utime, mi_msecs_t* stime, size_t* peak_rss, size_t* page_faults, size_t* page_reclaim, size_t* peak_commit) {
-  *peak_rss = 0;
+static void mi_stat_process_info(mi_msecs_t* elapsed, mi_msecs_t* utime, mi_msecs_t* stime, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults)
+{
+  *elapsed = _mi_clock_end(mi_process_start);
+  *peak_commit    = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.peak));
+  *current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)&_mi_stats_main.committed.current));
+  *peak_rss    = *peak_commit;
+  *current_rss = *current_commit;
   *page_faults = 0;
-  *page_reclaim = 0;
-  *peak_commit = 0;
   *utime = 0;
   *stime = 0;
 }
 #endif
+
+
+mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept
+{
+  mi_msecs_t elapsed = 0;
+  mi_msecs_t utime = 0;
+  mi_msecs_t stime = 0;
+  size_t current_rss0 = 0;
+  size_t peak_rss0 = 0;
+  size_t current_commit0 = 0;
+  size_t peak_commit0 = 0;
+  size_t page_faults0 = 0;  
+  mi_stat_process_info(&elapsed,&utime, &stime, &current_rss0, &peak_rss0, &current_commit0, &peak_commit0, &page_faults0);
+  if (elapsed_msecs!=NULL)  *elapsed_msecs = (elapsed < 0 ? 0 : (elapsed < (mi_msecs_t)PTRDIFF_MAX ? (size_t)elapsed : PTRDIFF_MAX));
+  if (user_msecs!=NULL)     *user_msecs     = (utime < 0 ? 0 : (utime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)utime : PTRDIFF_MAX));
+  if (system_msecs!=NULL)   *system_msecs   = (stime < 0 ? 0 : (stime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)stime : PTRDIFF_MAX));
+  if (current_rss!=NULL)    *current_rss    = current_rss0;
+  if (peak_rss!=NULL)       *peak_rss       = peak_rss0;
+  if (current_commit!=NULL) *current_commit = current_commit0;
+  if (peak_commit!=NULL)    *peak_commit    = peak_commit0;
+  if (page_faults!=NULL)    *page_faults    = page_faults0;
+}
+
index 4152f99d06d0316cd89de5792b35bc52553c11ec..bb8dc97e319b9f7b935eae5d6252b1be54d2854e 100644 (file)
@@ -1,6 +1,9 @@
 cmake_minimum_required(VERSION 3.0)
 project(mimalloc-test C CXX)
 
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+
 # Set default build type
 if (NOT CMAKE_BUILD_TYPE)
   if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$")
@@ -13,8 +16,8 @@ if (NOT CMAKE_BUILD_TYPE)
 endif()
 
 # Import mimalloc (if installed)
-find_package(mimalloc 1.6 REQUIRED NO_SYSTEM_ENVIRONMENT_PATH)
-message(STATUS "Found mimalloc installed at: ${MIMALLOC_TARGET_DIR}")
+find_package(mimalloc 2.0 REQUIRED NO_SYSTEM_ENVIRONMENT_PATH)
+message(STATUS "Found mimalloc installed at: ${MIMALLOC_LIBRARY_DIR} (${MIMALLOC_VERSION_DIR})")
 
 # overriding with a dynamic library
 add_executable(dynamic-override  main-override.c)
@@ -26,8 +29,8 @@ target_link_libraries(dynamic-override-cxx PUBLIC mimalloc)
 
 # overriding with a static object file works reliable as the symbols in the
 # object file have priority over those in library files
-add_executable(static-override-obj main-override.c ${MIMALLOC_TARGET_DIR}/mimalloc.o)
-target_include_directories(static-override-obj PUBLIC ${MIMALLOC_TARGET_DIR}/include)
+add_executable(static-override-obj main-override.c ${MIMALLOC_OBJECT_DIR}/mimalloc.o)
+target_include_directories(static-override-obj PUBLIC ${MIMALLOC_INCLUDE_DIR})
 target_link_libraries(static-override-obj PUBLIC pthread)
 
 
index f738c517feecd84b62078e4581e0536b4fd252bd..adc07aee931714f8592617cfc9ac3ff8e695383f 100644 (file)
@@ -7,41 +7,57 @@
 #include <mimalloc.h>
 #include <mimalloc-override.h>  // redefines malloc etc.
 
+
 static void double_free1();
 static void double_free2();
 static void corrupt_free();
 static void block_overflow1();
 static void invalid_free();
+static void test_aslr(void);
+static void test_process_info(void);
+static void test_reserved(void);
+static void negative_stat(void);
+static void alloc_huge(void);
+static void test_heap_walk(void);
 
 int main() {
   mi_version();
-
+  mi_stats_reset();
   // detect double frees and heap corruption
   // double_free1();
   // double_free2();
   // corrupt_free();
   // block_overflow1();
-  invalid_free();
-
+  // test_aslr();
+  // invalid_free();
+  // test_reserved();
+  // negative_stat();
+  // alloc_huge();
+  test_heap_walk();
+  
   void* p1 = malloc(78);
   void* p2 = malloc(24);
   free(p1);
   p1 = mi_malloc(8);
-  //char* s = strdup("hello\n");
+  char* s = strdup("hello\n");
   free(p2);
+  
   p2 = malloc(16);
   p1 = realloc(p1, 32);
   free(p1);
   free(p2);
-  //free(s);
-  //mi_collect(true);
-
+  free(s);
+  
   /* now test if override worked by allocating/freeing across the api's*/
   //p1 = mi_malloc(32);
   //free(p1);
   //p2 = malloc(32);
   //mi_free(p2);
-  mi_stats_print(NULL);
+  
+  //mi_collect(true);
+  //mi_stats_print(NULL);
+  
+  // test_process_info();
   return 0;
 }
 
@@ -121,3 +137,249 @@ static void corrupt_free() {
     malloc(SZ);
   }
 }
+
+static void test_aslr(void) {
+  void* p[256];
+  p[0] = malloc(378200);
+  p[1] = malloc(1134626);
+  printf("p1: %p, p2: %p\n", p[0], p[1]);
+}
+
+static void test_process_info(void) {
+  size_t elapsed = 0;
+  size_t user_msecs = 0;
+  size_t system_msecs = 0;
+  size_t current_rss = 0;
+  size_t peak_rss = 0;
+  size_t current_commit = 0;
+  size_t peak_commit = 0;
+  size_t page_faults = 0;  
+  for (int i = 0; i < 100000; i++) {
+    void* p = calloc(100,10);
+    free(p);
+  }
+  mi_process_info(&elapsed, &user_msecs, &system_msecs, &current_rss, &peak_rss, &current_commit, &peak_commit, &page_faults);
+  printf("\n\n*** process info: elapsed %3zd.%03zd s, user: %3zd.%03zd s, rss: %zd b, commit: %zd b\n\n", elapsed/1000, elapsed%1000, user_msecs/1000, user_msecs%1000, peak_rss, peak_commit);
+}
+
+static void test_reserved(void) {
+#define KiB 1024ULL
+#define MiB (KiB*KiB)
+#define GiB (MiB*KiB)
+  mi_reserve_os_memory(4*GiB, false, true);
+  void* p1 = malloc(100);
+  void* p2 = malloc(100000);
+  void* p3 = malloc(2*GiB);
+  void* p4 = malloc(1*GiB + 100000);
+  free(p1);
+  free(p2);
+  free(p3);
+  p3 = malloc(1*GiB);
+  free(p4);
+}
+
+
+
+static void negative_stat(void) {
+  int* p = mi_malloc(60000);
+  mi_stats_print_out(NULL, NULL);
+  *p = 100;
+  mi_free(p);
+  mi_stats_print_out(NULL, NULL);  
+}
+
+static void alloc_huge(void) {
+  void* p = mi_malloc(67108872);
+  mi_free(p);
+}
+
+static bool test_visit(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) {
+  if (block == NULL) {
+    printf("visiting an area with blocks of size %zu (including padding)\n", area->full_block_size);
+  }
+  else {
+    printf("  block of size %zu (allocated size is %zu)\n", block_size, mi_usable_size(block));
+  }
+  return true;
+}
+
+static void test_heap_walk(void) {
+  mi_heap_t* heap = mi_heap_new();
+  //mi_heap_malloc(heap, 2097152);
+  mi_heap_malloc(heap, 2067152);
+  mi_heap_malloc(heap, 2097160);
+  mi_heap_malloc(heap, 24576);
+  mi_heap_visit_blocks(heap, true, &test_visit, NULL);
+}
+
+// ----------------------------
+// bin size experiments
+// ------------------------------
+
+#if 0
+#include <stdint.h>
+#include <stdbool.h>
+
+#define MI_INTPTR_SIZE 8
+#define MI_LARGE_WSIZE_MAX (4*1024*1024 / MI_INTPTR_SIZE)
+
+#define MI_BIN_HUGE 100
+//#define MI_ALIGN2W
+
+// Bit scan reverse: return the index of the highest bit.
+static inline uint8_t mi_bsr32(uint32_t x);
+
+#if defined(_MSC_VER)
+#include <windows.h>
+#include <intrin.h>
+static inline uint8_t mi_bsr32(uint32_t x) {
+  uint32_t idx;
+  _BitScanReverse((DWORD*)&idx, x);
+  return idx;
+}
+#elif defined(__GNUC__) || defined(__clang__)
+static inline uint8_t mi_bsr32(uint32_t x) {
+  return (31 - __builtin_clz(x));
+}
+#else
+static inline uint8_t mi_bsr32(uint32_t x) {
+  // de Bruijn multiplication, see <http://supertech.csail.mit.edu/papers/debruijn.pdf>
+  static const uint8_t debruijn[32] = {
+     31,  0, 22,  1, 28, 23, 18,  2, 29, 26, 24, 10, 19,  7,  3, 12,
+     30, 21, 27, 17, 25,  9,  6, 11, 20, 16,  8,  5, 15,  4, 14, 13,
+  };
+  x |= x >> 1;
+  x |= x >> 2;
+  x |= x >> 4;
+  x |= x >> 8;
+  x |= x >> 16;
+  x++;
+  return debruijn[(x*0x076be629) >> 27];
+}
+#endif
+
+/*
+// Bit scan reverse: return the index of the highest bit.
+uint8_t _mi_bsr(uintptr_t x) {
+  if (x == 0) return 0;
+  #if MI_INTPTR_SIZE==8
+  uint32_t hi = (x >> 32);
+  return (hi == 0 ? mi_bsr32((uint32_t)x) : 32 + mi_bsr32(hi));
+  #elif MI_INTPTR_SIZE==4
+  return mi_bsr32(x);
+  #else
+  # error "define bsr for non-32 or 64-bit platforms"
+  #endif
+}
+*/
+
+
+static inline size_t _mi_wsize_from_size(size_t size) {
+  return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+}
+
+// Return the bin for a given field size.
+// Returns MI_BIN_HUGE if the size is too large.
+// We use `wsize` for the size in "machine word sizes",
+// i.e. byte size == `wsize*sizeof(void*)`.
+extern inline uint8_t _mi_bin8(size_t size) {
+  size_t wsize = _mi_wsize_from_size(size);
+  uint8_t bin;
+  if (wsize <= 1) {
+    bin = 1;
+  }
+#if defined(MI_ALIGN4W)
+  else if (wsize <= 4) {
+    bin = (uint8_t)((wsize+1)&~1); // round to double word sizes
+  }
+#elif defined(MI_ALIGN2W)
+  else if (wsize <= 8) {
+    bin = (uint8_t)((wsize+1)&~1); // round to double word sizes
+  }
+#else
+  else if (wsize <= 8) {
+    bin = (uint8_t)wsize;
+  }
+#endif
+  else if (wsize > MI_LARGE_WSIZE_MAX) {
+    bin = MI_BIN_HUGE;
+  }
+  else {
+#if defined(MI_ALIGN4W)
+    if (wsize <= 16) { wsize = (wsize+3)&~3; } // round to 4x word sizes
+#endif
+    wsize--;
+    // find the highest bit
+    uint8_t b = mi_bsr32((uint32_t)wsize);
+    // and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation).
+    // - adjust with 3 because we use do not round the first 8 sizes
+    //   which each get an exact bin
+    bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3;
+  }
+  return bin;
+}
+
+static inline uint8_t _mi_bin4(size_t size) {
+  size_t wsize = _mi_wsize_from_size(size);
+  uint8_t bin;
+  if (wsize <= 1) {
+    bin = 1;
+  }
+#if defined(MI_ALIGN4W)
+  else if (wsize <= 4) {
+    bin = (uint8_t)((wsize+1)&~1); // round to double word sizes
+  }
+#elif defined(MI_ALIGN2W)
+  else if (wsize <= 8) {
+    bin = (uint8_t)((wsize+1)&~1); // round to double word sizes
+  }
+#else
+  else if (wsize <= 8) {
+    bin = (uint8_t)wsize;
+  }
+#endif
+  else if (wsize > MI_LARGE_WSIZE_MAX) {
+    bin = MI_BIN_HUGE;
+  }
+  else {
+    uint8_t b = mi_bsr32((uint32_t)wsize);
+    bin = ((b << 1) + (uint8_t)((wsize >> (b - 1)) & 0x01)) + 3;
+  }
+  return bin;
+}
+
+static size_t _mi_binx4(size_t bsize) {
+  if (bsize==0) return 0;
+  uint8_t b = mi_bsr32((uint32_t)bsize);
+  if (b <= 1) return bsize;
+  size_t bin = ((b << 1) | (bsize >> (b - 1))&0x01);
+  return bin;
+}
+
+static size_t _mi_binx8(size_t bsize) {
+  if (bsize<=1) return bsize;
+  uint8_t b = mi_bsr32((uint32_t)bsize);
+  if (b <= 2) return bsize;
+  size_t bin = ((b << 2) | (bsize >> (b - 2))&0x03) - 5;
+  return bin;
+}
+
+static void mi_bins(void) {
+  //printf("  QNULL(1), /* 0 */ \\\n  ");
+  size_t last_bin = 0;
+  size_t min_bsize = 0;
+  size_t last_bsize = 0;
+  for (size_t bsize = 1; bsize < 2*1024; bsize++) {
+    size_t size = bsize * 64 * 1024;
+    size_t bin = _mi_binx8(bsize);
+    if (bin != last_bin) {
+      printf("min bsize: %6zd, max bsize: %6zd, bin: %6zd\n", min_bsize, last_bsize, last_bin);
+      //printf("QNULL(%6zd), ", wsize);
+      //if (last_bin%8 == 0) printf("/* %i */ \\\n  ", last_bin);
+      last_bin = bin;
+      min_bsize = bsize;
+    }
+    last_bsize = bsize;
+  }
+}
+#endif
index 1bec1179740704a23b7ecd399f82399e7ba64a70..284fdd2040c39f62d3be3fe49e4265a99c8e1c27 100644 (file)
@@ -3,7 +3,7 @@
 #include <assert.h>
 #include <string.h>
 
-#include <mimalloc.h>
+#include <mimalloc-override.h>
 
 int main() {
   mi_version();       // ensure mimalloc library is linked
@@ -25,6 +25,12 @@ int main() {
   //free(p1);
   //p2 = malloc(32);
   //mi_free(p2);
+  p1 = malloc(24);
+  p2 = reallocarray(p1, 16, 16);
+  free(p2);
+  p1 = malloc(24);
+  assert(reallocarr(&p1, 16, 16) == 0);
+  free(p1);
   mi_stats_print(NULL);
   return 0;
 }
index 16c40281c8ffd9d130a443623940041d970acc6e..e0dba5a3d77f6a1c479220233a8b3ebc6981d050 100644 (file)
 #endif
 
 #ifdef _WIN32
-#include <windows.h>
+#include <Windows.h>
 static void msleep(unsigned long msecs) { Sleep(msecs); }
 #else
 #include <unistd.h>
 static void msleep(unsigned long msecs) { usleep(msecs * 1000UL); }
 #endif
 
-void heap_thread_free_large(); // issue #221
-void heap_no_delete();         // issue #202
-void heap_late_free();         // issue #204
-void padding_shrink();         // issue #209
-void various_tests();
-void test_mt_shutdown();
+static void heap_thread_free_large(); // issue #221
+static void heap_no_delete();         // issue #202
+static void heap_late_free();         // issue #204
+static void padding_shrink();         // issue #209
+static void various_tests();
+static void test_mt_shutdown();
+static void large_alloc(void);        // issue #363
+static void fail_aslr();              // issue #372
+static void tsan_numa_test();         // issue #414
+static void strdup_test();            // issue #445 
+static void bench_alloc_large(void);  // issue #xxx
 
 int main() {
   mi_stats_reset();  // ignore earlier allocations
-  heap_thread_free_large();
-  heap_no_delete();
-  heap_late_free();
-  padding_shrink();
-  various_tests();
-  //test_mt_shutdown();
+
+   heap_thread_free_large();
+   heap_no_delete();
+   heap_late_free();
+   padding_shrink();
+   various_tests();
+   large_alloc();
+   tsan_numa_test();
+   strdup_test();
+
+  test_mt_shutdown();
+  //fail_aslr();
+  bench_alloc_large();
   mi_stats_print(NULL);
   return 0;
 }
@@ -61,26 +73,21 @@ public:
 };
 
 
-void various_tests() {
+static void various_tests() {
   atexit(free_p);
   void* p1 = malloc(78);
-  void* p2 = mi_malloc_aligned(16, 24);
+  void* p2 = mi_malloc_aligned(24, 16);
   free(p1);
   p1 = malloc(8);
   char* s = mi_strdup("hello\n");
 
-  //char* s = _strdup("hello\n");
-  //char* buf = NULL;
-  //size_t len;
-  //_dupenv_s(&buf,&len,"MIMALLOC_VERBOSE"); 
-  //mi_free(buf);
-
   mi_free(p2);
   p2 = malloc(16);
   p1 = realloc(p1, 32);
   free(p1);
   free(p2);
   mi_free(s);
+
   Test* t = new Test(42);
   delete t;
   t = new (std::nothrow) Test(42);
@@ -104,7 +111,7 @@ public:
 static Static s = Static();
 
 
-bool test_stl_allocator1() {
+static bool test_stl_allocator1() {
   std::vector<int, mi_stl_allocator<int> > vec;
   vec.push_back(1);
   vec.pop_back();
@@ -113,38 +120,48 @@ bool test_stl_allocator1() {
 
 struct some_struct { int i; int j; double z; };
 
-bool test_stl_allocator2() {
+static bool test_stl_allocator2() {
   std::vector<some_struct, mi_stl_allocator<some_struct> > vec;
   vec.push_back(some_struct());
   vec.pop_back();
   return vec.size() == 0;
 }
 
-
+// issue 445
+static void strdup_test() {
+#ifdef _MSC_VER
+  char* s = _strdup("hello\n");
+  char* buf = NULL;
+  size_t len;
+  _dupenv_s(&buf, &len, "MIMALLOC_VERBOSE");
+  mi_free(buf);
+  mi_free(s);
+#endif
+}
 
 // Issue #202
-void heap_no_delete_worker() {
+static void heap_no_delete_worker() {
   mi_heap_t* heap = mi_heap_new();
   void* q = mi_heap_malloc(heap, 1024);
   // mi_heap_delete(heap); // uncomment to prevent assertion
 }
 
-void heap_no_delete() {
+static void heap_no_delete() {
   auto t1 = std::thread(heap_no_delete_worker);
   t1.join();
 }
 
 
 // Issue #204
-volatile void* global_p;
+static volatile void* global_p;
 
-void t1main() {
+static void t1main() {
   mi_heap_t* heap = mi_heap_new();
   global_p = mi_heap_malloc(heap, 1024);
   mi_heap_delete(heap);
 }
 
-void heap_late_free() {
+static void heap_late_free() {
   auto t1 = std::thread(t1main);
 
   msleep(2000);
@@ -161,7 +178,7 @@ static void alloc0(/* void* arg */)
   shared_p = mi_malloc(8);
 }
 
-void padding_shrink(void)
+static void padding_shrink(void)
 {
   auto t1 = std::thread(alloc0);
   t1.join();
@@ -170,13 +187,13 @@ void padding_shrink(void)
 
 
 // Issue #221
-void heap_thread_free_large_worker() {
+static void heap_thread_free_large_worker() {
   mi_free(shared_p);
 }
 
-void heap_thread_free_large() {
+static void heap_thread_free_large() {
   for (int i = 0; i < 100; i++) {
-    shared_p = mi_malloc_aligned(2*1024*1024 + 1, 8);
+    shared_p = mi_malloc_aligned(2 * 1024 * 1024 + 1, 8);
     auto t1 = std::thread(heap_thread_free_large_worker);
     t1.join();
   }
@@ -184,7 +201,7 @@ void heap_thread_free_large() {
 
 
 
-void test_mt_shutdown()
+static void test_mt_shutdown()
 {
   const int threads = 5;
   std::vector< std::future< std::vector< char* > > > ts;
@@ -207,3 +224,66 @@ void test_mt_shutdown()
 
   std::cout << "done" << std::endl;
 }
+
+// issue #363
+using namespace std;
+
+void large_alloc(void)
+{
+  char* a = new char[1ull << 25];
+  thread th([&] {
+    delete[] a;
+    });
+  th.join();
+}
+
+// issue #372
+static void fail_aslr() {
+  size_t sz = (4ULL << 40); // 4TiB
+  void* p = malloc(sz);
+  printf("pointer p: %p: area up to %p\n", p, (uint8_t*)p + sz);
+  *(int*)0x5FFFFFFF000 = 0;  // should segfault
+}
+
+// issues #414
+static void dummy_worker() {
+  void* p = mi_malloc(0);
+  mi_free(p);
+}
+
+static void tsan_numa_test() {
+  auto t1 = std::thread(dummy_worker);
+  dummy_worker();
+  t1.join();
+}
+
+// issue #?
+#include <chrono>
+#include <random>
+#include <iostream>
+
+static void bench_alloc_large(void) {
+  static constexpr int kNumBuffers = 20;
+  static constexpr size_t kMinBufferSize = 5 * 1024 * 1024;
+  static constexpr size_t kMaxBufferSize = 25 * 1024 * 1024;
+  std::unique_ptr<char[]> buffers[kNumBuffers];
+
+  std::random_device rd;
+  std::mt19937 gen(42); //rd());
+  std::uniform_int_distribution<> size_distribution(kMinBufferSize, kMaxBufferSize);
+  std::uniform_int_distribution<> buf_number_distribution(0, kNumBuffers - 1);
+
+  static constexpr int kNumIterations = 2000;
+  const auto start = std::chrono::steady_clock::now();
+  for (int i = 0; i < kNumIterations; ++i) {
+    int buffer_idx = buf_number_distribution(gen);
+    size_t new_size = size_distribution(gen);
+    buffers[buffer_idx] = std::make_unique<char[]>(new_size);
+  }
+  const auto end = std::chrono::steady_clock::now();
+  const auto num_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+  const auto us_per_allocation = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / kNumIterations;
+  std::cout << kNumIterations << " allocations Done in " << num_ms << "ms." << std::endl;
+  std::cout << "Avg " << us_per_allocation << " us per allocation" << std::endl;
+}
+
diff --git a/extlib/mimalloc/test/test-api-fill.c b/extlib/mimalloc/test/test-api-fill.c
new file mode 100644 (file)
index 0000000..0e5a65d
--- /dev/null
@@ -0,0 +1,332 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+#include "mimalloc.h"
+#include "mimalloc-types.h"
+
+#include "testhelper.h"
+
+// ---------------------------------------------------------------------------
+// Helper functions
+// ---------------------------------------------------------------------------
+bool check_zero_init(uint8_t* p, size_t size);
+#if MI_DEBUG >= 2
+bool check_debug_fill_uninit(uint8_t* p, size_t size);
+bool check_debug_fill_freed(uint8_t* p, size_t size);
+#endif
+
+// ---------------------------------------------------------------------------
+// Main testing
+// ---------------------------------------------------------------------------
+int main(void) {
+  mi_option_disable(mi_option_verbose);
+
+  // ---------------------------------------------------
+  // Zeroing allocation
+  // ---------------------------------------------------
+  CHECK_BODY("zeroinit-zalloc-small", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+    result = check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-zalloc-large", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+    result = check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-zalloc_small", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_zalloc_small(zalloc_size);
+    result = check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-calloc-small", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+    result = check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-calloc-large", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+    result = check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-rezalloc-small", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+    result = check_zero_init(p, zalloc_size);
+    zalloc_size *= 3;
+    p = (uint8_t*)mi_rezalloc(p, zalloc_size);
+    result &= check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-rezalloc-large", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size);
+    result = check_zero_init(p, zalloc_size);
+    zalloc_size *= 3;
+    p = (uint8_t*)mi_rezalloc(p, zalloc_size);
+    result &= check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-recalloc-small", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+    result = check_zero_init(p, calloc_size);
+    calloc_size *= 3;
+    p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
+    result &= check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-recalloc-large", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1);
+    result = check_zero_init(p, calloc_size);
+    calloc_size *= 3;
+    p = (uint8_t*)mi_recalloc(p, calloc_size, 1);
+    result &= check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+
+  // ---------------------------------------------------
+  // Zeroing in aligned API
+  // ---------------------------------------------------
+  CHECK_BODY("zeroinit-zalloc_aligned-small", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-zalloc_aligned-large", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-calloc_aligned-small", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-calloc_aligned-large", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-rezalloc_aligned-small", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, zalloc_size);
+    zalloc_size *= 3;
+    p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-rezalloc_aligned-large", {
+    size_t zalloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, zalloc_size);
+    zalloc_size *= 3;
+    p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_zero_init(p, zalloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("zeroinit-recalloc_aligned-small", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, calloc_size);
+    calloc_size *= 3;
+    p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("zeroinit-recalloc_aligned-large", {
+    size_t calloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result = check_zero_init(p, calloc_size);
+    calloc_size *= 3;
+    p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_zero_init(p, calloc_size);
+    mi_free(p);
+  });
+
+#if MI_DEBUG >= 2
+  // ---------------------------------------------------
+  // Debug filling
+  // ---------------------------------------------------
+  CHECK_BODY("uninit-malloc-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-malloc-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-malloc_small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc_small(malloc_size);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-realloc-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_realloc(p, malloc_size);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-realloc-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_realloc(p, malloc_size);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-mallocn-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-mallocn-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-reallocn-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-reallocn-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_reallocn(p, malloc_size, 1);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-malloc_aligned-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-malloc_aligned-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+  CHECK_BODY("uninit-realloc_aligned-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+  CHECK_BODY("uninit-realloc_aligned-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result = check_debug_fill_uninit(p, malloc_size);
+    malloc_size *= 3;
+    p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2);
+    result &= check_debug_fill_uninit(p, malloc_size);
+    mi_free(p);
+  });
+
+
+  CHECK_BODY("fill-freed-small", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX / 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    mi_free(p);
+    // First sizeof(void*) bytes will contain housekeeping data, skip these
+    result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
+  });
+  CHECK_BODY("fill-freed-large", {
+    size_t malloc_size = MI_SMALL_SIZE_MAX * 2;
+    uint8_t* p = (uint8_t*)mi_malloc(malloc_size);
+    mi_free(p);
+    // First sizeof(void*) bytes will contain housekeeping data, skip these
+    result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*));
+  });
+#endif
+
+  // ---------------------------------------------------
+  // Done
+  // ---------------------------------------------------[]
+  return print_test_summary();
+}
+
+// ---------------------------------------------------------------------------
+// Helper functions
+// ---------------------------------------------------------------------------
+bool check_zero_init(uint8_t* p, size_t size) {
+  if(!p)
+    return false;
+  bool result = true;
+  for (size_t i = 0; i < size; ++i) {
+    result &= p[i] == 0;
+  }
+  return result;
+}
+
+#if MI_DEBUG >= 2
+bool check_debug_fill_uninit(uint8_t* p, size_t size) {
+  if(!p)
+    return false;
+
+  bool result = true;
+  for (size_t i = 0; i < size; ++i) {
+    result &= p[i] == MI_DEBUG_UNINIT;
+  }
+  return result;
+}
+
+bool check_debug_fill_freed(uint8_t* p, size_t size) {
+  if(!p)
+    return false;
+
+  bool result = true;
+  for (size_t i = 0; i < size; ++i) {
+    result &= p[i] == MI_DEBUG_FREED;
+  }
+  return result;
+}
+#endif
index e5827a93eeb570bcf4b8d77982526e46485b9eb2..0302464e51cd1c0fd04158595a641a4d44fbcb1f 100644 (file)
@@ -1,9 +1,12 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018, Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license. A copy of the license can be found in the file
 "LICENSE" at the root of this distribution.
 -----------------------------------------------------------------------------*/
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
+#endif
 
 /*
 Testing allocators is difficult as bugs may only surface after particular
@@ -20,7 +23,6 @@ we therefore test the API over various inputs. Please add more tests :-)
 [1] https://github.com/daanx/mimalloc-bench
 */
 
-#include <stdio.h>
 #include <assert.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -32,47 +34,22 @@ we therefore test the API over various inputs. Please add more tests :-)
 
 #include "mimalloc.h"
 // #include "mimalloc-internal.h"
+#include "mimalloc-types.h" // for MI_DEBUG
 
-// ---------------------------------------------------------------------------
-// Test macros: CHECK(name,predicate) and CHECK_BODY(name,body)
-// ---------------------------------------------------------------------------
-static int ok = 0;
-static int failed = 0;
-
-#define CHECK_BODY(name,body) \
- do { \
-  fprintf(stderr,"test: %s...  ", name ); \
-  bool result = true;                                     \
-  do { body } while(false);                                \
-  if (!(result)) {                                        \
-    failed++; \
-    fprintf(stderr,                                       \
-            "\n  FAILED: %s:%d:\n  %s\n",                 \
-            __FILE__,                                     \
-            __LINE__,                                     \
-            #body);                                       \
-    /* exit(1); */ \
-  } \
-  else { \
-    ok++;                               \
-    fprintf(stderr,"ok.\n");                    \
-  }                                             \
- } while (false)
-
-#define CHECK(name,expr)      CHECK_BODY(name,{ result = (expr); })
+#include "testhelper.h"
 
 // ---------------------------------------------------------------------------
 // Test functions
 // ---------------------------------------------------------------------------
-bool test_heap1();
-bool test_heap2();
-bool test_stl_allocator1();
-bool test_stl_allocator2();
+bool test_heap1(void);
+bool test_heap2(void);
+bool test_stl_allocator1(void);
+bool test_stl_allocator2(void);
 
 // ---------------------------------------------------------------------------
 // Main testing
 // ---------------------------------------------------------------------------
-int main() {
+int main(void) {
   mi_option_disable(mi_option_verbose);
 
   // ---------------------------------------------------
@@ -83,7 +60,7 @@ int main() {
     void* p = mi_malloc(0); mi_free(p);
   });
   CHECK_BODY("malloc-nomem1",{
-    result = (mi_malloc(SIZE_MAX/2) == NULL);
+    result = (mi_malloc((size_t)PTRDIFF_MAX + (size_t)1) == NULL);
   });
   CHECK_BODY("malloc-null",{
     mi_free(NULL);
@@ -95,6 +72,10 @@ int main() {
   CHECK_BODY("calloc0",{
     result = (mi_usable_size(mi_calloc(0,1000)) <= 16);
   });
+  CHECK_BODY("malloc-large",{   // see PR #544.
+    void* p = mi_malloc(67108872);
+    mi_free(p);
+  });
 
   // ---------------------------------------------------
   // Extended
@@ -155,6 +136,28 @@ int main() {
   CHECK_BODY("malloc-aligned5", {
     void* p = mi_malloc_aligned(4097,4096); size_t usable = mi_usable_size(p); result = usable >= 4097 && usable < 10000; mi_free(p);
   });
+  CHECK_BODY("malloc-aligned6", {
+    bool ok = true;
+    for (size_t align = 1; align <= MI_ALIGNMENT_MAX && ok; align *= 2) {
+      void* ps[8];
+      for (int i = 0; i < 8 && ok; i++) {
+        ps[i] = mi_malloc_aligned(align*13 /*size*/, align);
+        if (ps[i] == NULL || (uintptr_t)(ps[i]) % align != 0) {
+          ok = false;
+        }
+      }
+      for (int i = 0; i < 8 && ok; i++) {
+        mi_free(ps[i]);
+      }
+    }
+    result = ok;
+  });
+  CHECK_BODY("malloc-aligned7", {
+    void* p = mi_malloc_aligned(1024,MI_ALIGNMENT_MAX); mi_free(p);
+    });
+  CHECK_BODY("malloc-aligned8", {
+    void* p = mi_malloc_aligned(1024,2*MI_ALIGNMENT_MAX); mi_free(p);
+  });
   CHECK_BODY("malloc-aligned-at1", {
     void* p = mi_malloc_aligned_at(48,32,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 32 == 0); mi_free(p);
   });
@@ -169,8 +172,8 @@ int main() {
       ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p);
     }
     result = ok;
-    });
-
+  });
+  
   // ---------------------------------------------------
   // Heaps
   // ---------------------------------------------------
@@ -194,10 +197,7 @@ int main() {
   // ---------------------------------------------------
   // Done
   // ---------------------------------------------------[]
-  fprintf(stderr,"\n\n---------------------------------------------\n"
-                 "succeeded: %i\n"
-                 "failed   : %i\n\n", ok, failed);
-  return failed;
+  return print_test_summary();
 }
 
 // ---------------------------------------------------
index 7d8993a0db0843a61199490a94c2997de4378ca9..ff5fffeb12e88c146cd250b2ae22fa55be76fcdf 100644 (file)
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
-Copyright (c) 2018,2019 Microsoft Research, Daan Leijen
+Copyright (c) 2018-2020 Microsoft Research, Daan Leijen
 This is free software; you can redistribute it and/or modify it under the
 terms of the MIT license.
 -----------------------------------------------------------------------------*/
@@ -20,13 +20,12 @@ terms of the MIT license.
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
-#include <mimalloc.h>
 
 // > mimalloc-test-stress [THREADS] [SCALE] [ITER]
 //
 // argument defaults
 static int THREADS = 32;      // more repeatable if THREADS <= #processors
-static int SCALE   = 10;      // scaling factor
+static int SCALE   = 25;      // scaling factor
 static int ITER    = 50;      // N full iterations destructing and re-creating all threads
 
 // static int THREADS = 8;    // more repeatable if THREADS <= #processors
@@ -38,12 +37,14 @@ static bool   allow_large_objects = true;    // allow very large objects?
 static size_t use_one_size = 0;              // use single object size of `N * sizeof(uintptr_t)`?
 
 
+// #define USE_STD_MALLOC
 #ifdef USE_STD_MALLOC
-#define custom_calloc(n,s)    calloc(n,s)
+#define custom_calloc(n,s)    malloc(n*s)
 #define custom_realloc(p,s)   realloc(p,s)
 #define custom_free(p)        free(p)
 #else
-#define custom_calloc(n,s)    mi_calloc(n,s)
+#include <mimalloc.h>
+#define custom_calloc(n,s)    mi_malloc(n*s)
 #define custom_realloc(p,s)   mi_realloc(p,s)
 #define custom_free(p)        mi_free(p)
 #endif
@@ -123,7 +124,7 @@ static void free_items(void* p) {
 
 static void stress(intptr_t tid) {
   //bench_start_thread();
-  uintptr_t r = (tid * 43); // rand();
+  uintptr_t r = ((tid + 1) * 43); // rand();
   const size_t max_item_shift = 5; // 128
   const size_t max_item_retained_shift = max_item_shift + 2;
   size_t allocs = 100 * ((size_t)SCALE) * (tid % 8 + 1); // some threads do more
@@ -181,17 +182,20 @@ static void run_os_threads(size_t nthreads, void (*entry)(intptr_t tid));
 static void test_stress(void) {
   uintptr_t r = rand();
   for (int n = 0; n < ITER; n++) {
-    run_os_threads(THREADS, &stress);
+    run_os_threads(THREADS, &stress);    
     for (int i = 0; i < TRANSFERS; i++) {
       if (chance(50, &r) || n + 1 == ITER) { // free all on last run, otherwise free half of the transfers
         void* p = atomic_exchange_ptr(&transfer[i], NULL);
         free_items(p);
       }
     }
-    // mi_collect(false);
-#ifndef NDEBUG
+    #ifndef NDEBUG
+    //mi_collect(false);
+    //mi_debug_show_arenas();
+    #endif    
+    #if !defined(NDEBUG) || defined(MI_TSAN)
     if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); }
-#endif
+    #endif
   }
 }
 
@@ -217,7 +221,7 @@ static void test_leak(void) {
 }
 #endif
 
-int main(int argc, char** argv) {
+int main(int argc, char** argv) {  
   // > mimalloc-test-stress [THREADS] [SCALE] [ITER]
   if (argc >= 2) {
     char* end;
@@ -235,6 +239,7 @@ int main(int argc, char** argv) {
     if (n > 0) ITER = n;
   }
   printf("Using %d threads with a %d%% load-per-thread and %d iterations\n", THREADS, SCALE, ITER);
+  //mi_reserve_os_memory(1024*1024*1024ULL, false, true);
   //int res = mi_reserve_huge_os_pages(4,1);
   //printf("(reserve huge: %i\n)", res);
 
@@ -242,15 +247,26 @@ int main(int argc, char** argv) {
 
   // Run ITER full iterations where half the objects in the transfer buffer survive to the next round.
   srand(0x7feb352d);
-  // mi_stats_reset();
+  
+  //mi_reserve_os_memory(512ULL << 20, true, true);
+
+#if !defined(NDEBUG) && !defined(USE_STD_MALLOC)
+  mi_stats_reset();
+#endif
+
 #ifdef STRESS
-    test_stress();
+  test_stress();
 #else
-    test_leak();
+  test_leak();
 #endif
 
-  // mi_collect(true);
+#ifndef USE_STD_MALLOC
+  #ifndef NDEBUG
+  mi_collect(true);
+  //mi_debug_show_arenas();
+  #endif
   mi_stats_print(NULL);
+#endif
   //bench_end_program();
   return 0;
 }
@@ -260,7 +276,7 @@ static void (*thread_entry_fun)(intptr_t) = &stress;
 
 #ifdef _WIN32
 
-#include <windows.h>
+#include <Windows.h>
 
 static DWORD WINAPI thread_entry(LPVOID param) {
   thread_entry_fun((intptr_t)param);
@@ -272,7 +288,7 @@ static void run_os_threads(size_t nthreads, void (*fun)(intptr_t)) {
   DWORD* tids = (DWORD*)custom_calloc(nthreads,sizeof(DWORD));
   HANDLE* thandles = (HANDLE*)custom_calloc(nthreads,sizeof(HANDLE));
   for (uintptr_t i = 0; i < nthreads; i++) {
-    thandles[i] = CreateThread(0, 4096, &thread_entry, (void*)(i), 0, &tids[i]);
+    thandles[i] = CreateThread(0, 8*1024, &thread_entry, (void*)(i), 0, &tids[i]);
   }
   for (size_t i = 0; i < nthreads; i++) {
     WaitForSingleObject(thandles[i], INFINITE);
@@ -305,7 +321,7 @@ static void run_os_threads(size_t nthreads, void (*fun)(intptr_t)) {
   pthread_t* threads = (pthread_t*)custom_calloc(nthreads,sizeof(pthread_t));
   memset(threads, 0, sizeof(pthread_t) * nthreads);
   //pthread_setconcurrency(nthreads);
-  for (uintptr_t i = 0; i < nthreads; i++) {
+  for (size_t i = 0; i < nthreads; i++) {
     pthread_create(&threads[i], NULL, &thread_entry, (void*)i);
   }
   for (size_t i = 0; i < nthreads; i++) {
diff --git a/extlib/mimalloc/test/testhelper.h b/extlib/mimalloc/test/testhelper.h
new file mode 100644 (file)
index 0000000..46d63a0
--- /dev/null
@@ -0,0 +1,49 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2018-2020, Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+#ifndef TESTHELPER_H_
+#define TESTHELPER_H_
+
+#include <stdio.h>
+
+// ---------------------------------------------------------------------------
+// Test macros: CHECK(name,predicate) and CHECK_BODY(name,body)
+// ---------------------------------------------------------------------------
+static int ok = 0;
+static int failed = 0;
+
+#define CHECK_BODY(name,body) \
+ do { \
+  fprintf(stderr,"test: %s...  ", name ); \
+  bool result = true;                                     \
+  do { body } while(false);                                \
+  if (!(result)) {                                        \
+    failed++; \
+    fprintf(stderr,                                       \
+            "\n  FAILED: %s:%d:\n  %s\n",                 \
+            __FILE__,                                     \
+            __LINE__,                                     \
+            #body);                                       \
+    /* exit(1); */ \
+  } \
+  else { \
+    ok++;                               \
+    fprintf(stderr,"ok.\n");                    \
+  }                                             \
+ } while (false)
+
+#define CHECK(name,expr)      CHECK_BODY(name,{ result = (expr); })
+
+// Print summary of test. Return value can be directly use as a return value for main().
+static inline int print_test_summary(void)
+{
+  fprintf(stderr,"\n\n---------------------------------------------\n"
+                 "succeeded: %i\n"
+                 "failed   : %i\n\n", ok, failed);
+  return failed;
+}
+
+#endif // TESTHELPER_H_
index 1c97fbf82a6b8160f51a13ca9707084c4ee2f6d3..458f8c0d8ea753c8fdf054f66185daa0642c9887 100644 (file)
@@ -113,6 +113,10 @@ typedef struct {
 #define SLVS_C_WHERE_DRAGGED            100031
 #define SLVS_C_CURVE_CURVE_TANGENT      100032
 #define SLVS_C_LENGTH_DIFFERENCE        100033
+#define SLVS_C_ARC_ARC_LEN_RATIO        100034
+#define SLVS_C_ARC_LINE_LEN_RATIO       100035
+#define SLVS_C_ARC_ARC_DIFFERENCE       100036
+#define SLVS_C_ARC_LINE_DIFFERENCE      100037
 
 typedef struct {
     Slvs_hConstraint    h;
diff --git a/pkg/flatpak/.gitignore b/pkg/flatpak/.gitignore
deleted file mode 100644 (file)
index ca1b1d7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/.flatpak-builder
-/build-dir
-/repo
-*.flatpak
index 8c4ce5137664b468410176672b6f9953746a26a1..8f55fa848572a3bd208179fbf24d2b814cdee1f1 100644 (file)
@@ -1,19 +1,29 @@
 {
     "app-id": "com.solvespace.SolveSpace",
-    "runtime": "org.gnome.Platform",
-    "runtime-version": "3.30",
-    "sdk": "org.gnome.Sdk",
+    "runtime": "org.freedesktop.Platform",
+    "runtime-version": "20.08",
+    "sdk": "org.freedesktop.Sdk",
     "finish-args": [
         /* Access to display server and OpenGL */
-        "--share=ipc", "--socket=fallback-x11", "--socket=wayland", "--device=dri",
+        "--share=ipc",
+        "--socket=fallback-x11",
+        "--socket=wayland",
+        "--device=dri",
         /* Access to save files */
         "--filesystem=home"
     ],
     "cleanup": [
-        "/include", "/lib/*/include",
-        "*.a", "*.la", "*.m4", "/lib/libslvs*.so*", "/lib/libglibmm_generate_extra_defs*.so*",
-        "/share/pkgconfig", "*.pc",
-        "/share/man", "/share/doc",
+        "/include",
+        "/lib/*/include",
+        "*.a",
+        "*.la",
+        "*.m4",
+        "/lib/libslvs*.so*",
+        "/lib/libglibmm_generate_extra_defs*.so*",
+        "/share/pkgconfig",
+        "*.pc",
+        "/share/man",
+        "/share/doc",
         "/share/aclocal",
         /* mm-common junk */
         "/bin/mm-common-prepare",
@@ -26,8 +36,8 @@
             "sources": [
                 {
                     "type": "archive",
-                    "url": "http://ftp.gnome.org/pub/GNOME/sources/mm-common/0.9/mm-common-0.9.12.tar.xz",
-                    "sha256": "ceffdcce1e5b52742884c233ec604bf6fded12eea9da077ce7a62c02c87e7c0b"
+                    "url": "https://download.gnome.org/sources/mm-common/1.0/mm-common-1.0.2.tar.xz",
+                    "sha256": "a2a99f3fa943cf662f189163ed39a2cfc19a428d906dd4f92b387d3659d1641d"
                 }
             ]
         },
             "sources": [
                 {
                     "type": "archive",
-                    "url": "http://ftp.gnome.org/pub/GNOME/sources/libsigc++/2.10/libsigc++-2.10.1.tar.xz",
-                    "sha256": "c9a25f26178c6cbb147f9904d8c533b5a5c5111a41ac2eb781eb734eea446003"
+                    "url": "https://download.gnome.org/sources/libsigc++/2.10/libsigc%2B%2B-2.10.6.tar.xz",
+                    "sha256": "dda176dc4681bda9d5a2ac1bc55273bdd381662b7a6d49e918267d13e8774e1b"
                 }
             ]
         },
         {
             "name": "glibmm",
-            "config-opts": [
-                "--disable-documentation"
-            ],
+            "config-opts": [],
+            "buildsystem": "meson",
             "sources": [
                 {
                     "type": "archive",
-                    "url": "http://ftp.gnome.org/pub/GNOME/sources/glibmm/2.58/glibmm-2.58.1.tar.xz",
-                    "sha256": "6e5fe03bdf1e220eeffd543e017fd2fb15bcec9235f0ffd50674aff9362a85f0"
+                    "url": "https://download.gnome.org/sources/glibmm/2.64/glibmm-2.64.5.tar.xz",
+                    "sha256": "508fc86e2c9141198aa16c225b16fd6b911917c0d3817602652844d0973ea386"
                 }
             ]
         },
         },
         {
             "name": "gtkmm",
-            "config-opts": [
-                "--disable-documentation"
-            ],
+            "config-opts": [],
+            "buildsystem": "meson",
             "sources": [
                 {
                     "type": "archive",
-                    "url": "http://ftp.gnome.org/pub/GNOME/sources/gtkmm/3.24/gtkmm-3.24.1.tar.xz",
-                    "sha256": "ddfe42ed2458a20a34de252854bcf4b52d3f0c671c045f56b42aa27c7542d2fd"
+                    "url": "https://download.gnome.org/sources/gtkmm/3.24/gtkmm-3.24.4.tar.xz",
+                    "sha256": "9beb71c3e90cfcfb790396b51e3f5e7169966751efd4f3ef9697114be3be6743"
                 }
             ]
         },
             "name": "libjson-c",
             "sources": [
                 {
+                    /* 0.15-nodoc doesn't build */
                     "type": "archive",
                     "url": "https://s3.amazonaws.com/json-c_releases/releases/json-c-0.13.1-nodoc.tar.gz",
                     "sha256": "94a26340c0785fcff4f46ff38609cf84ebcd670df0c8efd75d039cc951d80132"
             "name": "SolveSpace",
             "sources": [
                 {
-                    "type": "git",
-                    "path": "/home/whitequark/Projects/solvespace"
+                    "type": "dir",
+                    "path": "../.."
                 }
             ],
             "buildsystem": "cmake",
diff --git a/pkg/snap/.gitignore b/pkg/snap/.gitignore
deleted file mode 100644 (file)
index 9f938db..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-*.snap
-solvespace-snap-src
-squashfs-root
index 5fe5f7be64f4c6e1252b29865755a6c5249356c4..b01b25cff72d0343614014f96e9c4b867f451173 100644 (file)
@@ -1,5 +1,5 @@
 name: solvespace
-base: core18
+base: core20
 summary: Parametric 2d/3d CAD
 adopt-info: solvespace
 description: |
@@ -14,6 +14,7 @@ description: |
 
 confinement: strict
 license: GPL-3.0
+compression: lzo
 
 layout:
   /usr/share/solvespace:
@@ -23,13 +24,11 @@ apps:
   solvespace:
     command: usr/bin/solvespace
     desktop: solvespace.desktop
-    extensions: [gnome-3-34]
+    extensions: [gnome-3-38]
     plugs: [opengl, unity7, home, removable-media, gsettings, network]
-    environment:
-      __EGL_VENDOR_LIBRARY_DIRS: $SNAP/gnome-platform/usr/share/glvnd/egl_vendor.d:$SNAP/usr/share/glvnd/egl_vendor.d
   cli:
     command: usr/bin/solvespace-cli
-    extensions: [gnome-3-34]
+    extensions: [gnome-3-38]
     plugs: [home, removable-media, network]
 
 parts:
@@ -39,23 +38,28 @@ parts:
     source-type: local
     override-pull: |
       snapcraftctl pull
-      version_major=$(grep "solvespace_VERSION_MAJOR" CMakeLists.txt | tr -d "()" | cut -d" " -f2)
-      version_minor=$(grep "solvespace_VERSION_MINOR" CMakeLists.txt | tr -d "()" | cut -d" " -f2)
-      version="$version_major.$version_minor~$(git rev-parse --short=8 HEAD)"
+      git submodule update --init extlib/libdxfrw extlib/mimalloc extlib/eigen
+    override-build: |
+      snapcraftctl build
+      project_version=$(grep CMAKE_PROJECT_VERSION:STATIC CMakeCache.txt | cut -d "=" -f2)
+      cd $SNAPCRAFT_PART_SRC
+      version="$project_version~$(git rev-parse --short=8 HEAD)"
       snapcraftctl set-version "$version"
       git describe --exact-match HEAD && grade="stable" || grade="devel"
       snapcraftctl set-grade "$grade"
-      git submodule update --init extlib/libdxfrw extlib/mimalloc
-    configflags:
+    cmake-parameters:
       - -DCMAKE_INSTALL_PREFIX=/usr
       - -DCMAKE_BUILD_TYPE=Release
       - -DENABLE_TESTS=OFF
       - -DSNAP=ON
       - -DENABLE_OPENMP=ON
       - -DENABLE_LTO=ON
+    build-snaps:
+      - gnome-3-38-2004-sdk
     build-packages:
       - zlib1g-dev
       - libpng-dev
+      - libcairo2-dev
       - libfreetype6-dev
       - libjson-c-dev
       - libgl-dev
@@ -70,11 +74,14 @@ parts:
   cleanup:
     after: [solvespace]
     plugin: nil
-    build-snaps: [core18, gnome-3-34-1804]
+    build-snaps: [gnome-3-38-2004]
     override-prime: |
-      # Remove all files from snap that are already included in the base snap or in
-      # any connected content snaps
       set -eux
-      for snap in "core18" "gnome-3-34-1804"; do  # List all content-snaps and base snaps you're using here
-        cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" \;
+      for snap in "gnome-3-38-2004"; do  # List all content-snaps you're using here
+        cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" "$SNAPCRAFT_PRIME/usr/{}" \;
       done
+      for cruft in bug lintian man; do
+        rm -rf $SNAPCRAFT_PRIME/usr/share/$cruft
+      done
+      find $SNAPCRAFT_PRIME/usr/share/doc/ -type f -not -name 'copyright' -delete
+      find $SNAPCRAFT_PRIME/usr/share -type d -empty -delete
index e261ba2134b36d0f8745a6d57ab415df725fa55e..7303c6f7a4d217911cc9bf43b5eb6e2bf0e73605 100644 (file)
@@ -31,7 +31,7 @@ if(WIN32)
         set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${source}")
     endfunction()
 elseif(APPLE)
-    set(app_resource_dir ${CMAKE_BINARY_DIR}/bin/SolveSpace.app/Contents/Resources)
+    set(app_resource_dir ${CMAKE_BINARY_DIR}/Resources)
     set(cli_resource_dir ${CMAKE_BINARY_DIR}/res)
 
     function(add_resource name)
@@ -134,6 +134,13 @@ else()
             DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications
             RENAME      com.solvespace.SolveSpace.desktop)
 
+        set(DESKTOP_FILE_NAME com.solvespace.SolveSpace.desktop)
+        configure_file(
+            ${CMAKE_CURRENT_SOURCE_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml.in
+            ${CMAKE_CURRENT_BINARY_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml)
+        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml
+            DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
+
         install(FILES freedesktop/solvespace-flatpak-mime.xml
             DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mime/packages
             RENAME      com.solvespace.SolveSpace-slvs.xml)
@@ -176,6 +183,13 @@ else()
         install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freedesktop/solvespace.desktop
             DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
 
+        set(DESKTOP_FILE_NAME solvespace.desktop)
+        configure_file(
+            ${CMAKE_CURRENT_SOURCE_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml.in
+            ${CMAKE_CURRENT_BINARY_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml)
+        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freedesktop/com.solvespace.SolveSpace.metainfo.xml
+            DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo)
+
         install(FILES freedesktop/solvespace-mime.xml
             DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mime/packages
             RENAME      solvespace-slvs.xml)
@@ -185,7 +199,7 @@ else()
             RENAME      solvespace.svg)
         install(FILES freedesktop/solvespace-scalable.svg
             DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/mimetypes
-            RENAME      application.x-solvespace.svg)
+            RENAME      application-x-solvespace.svg)
 
         foreach(SIZE 16x16 24x24 32x32 48x48)
             install(FILES freedesktop/solvespace-${SIZE}.png
@@ -193,12 +207,7 @@ else()
                 RENAME      solvespace.png)
             install(FILES freedesktop/solvespace-${SIZE}.png
                 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}/mimetypes
-                RENAME      application.x-solvespace.png)
-        endforeach()
-
-        foreach(SIZE 16x16 24x24 32x32 48x48)
-            install(FILES freedesktop/solvespace-${SIZE}.xpm
-                DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps)
+                RENAME      application-x-solvespace.png)
         endforeach()
     endif()
 endif()
@@ -257,6 +266,8 @@ add_resources(
     locales/en_US.po
     locales/fr_FR.po
     locales/uk_UA.po
+    locales/es_AR.po
+    locales/tr_TR.po
     locales/ru_RU.po
     locales/zh_CN.po
     fonts/unifont.hex.gz
@@ -284,7 +295,7 @@ add_resources(
     shaders/edge.frag
     shaders/edge.vert
     shaders/outline.vert
-    threejs/three-r76.js.gz
+    threejs/three-r111.min.js.gz
     threejs/hammer-2.0.8.js.gz
     threejs/SolveSpaceControls.js)
 
index ec0501dd9569e287ba85ad055a799b9d28296807..6d35aecf6bca69f87886c7d51db5d1bc25ec0caa 100644 (file)
Binary files a/res/fonts/unicode.lff.gz and b/res/fonts/unicode.lff.gz differ
diff --git a/res/fonts/unifont.hex.gz b/res/fonts/unifont.hex.gz
new file mode 100644 (file)
index 0000000..db7a710
Binary files /dev/null and b/res/fonts/unifont.hex.gz differ
diff --git a/res/freedesktop/com.solvespace.SolveSpace.metainfo.xml.in b/res/freedesktop/com.solvespace.SolveSpace.metainfo.xml.in
new file mode 100644 (file)
index 0000000..3e88165
--- /dev/null
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop-application">
+  <id>com.solvespace.SolveSpace</id>
+
+  <name>SolveSpace</name>
+  <summary>A free (GPLv3) parametric 3d CAD tool</summary>
+
+  <metadata_license>CC0-1.0</metadata_license>
+  <project_license>GPL-3.0-or-later</project_license>
+  <update_contact>ryan_AT_ryanpavlik.com</update_contact>
+
+  <categories>
+    <category>Graphics</category>
+    <category>3DGraphics</category>
+    <category>Engineering</category>
+  </categories>
+  <description>
+    <p>
+      SolveSpace is a free (GPLv3) parametric 3d CAD tool. Applications include:
+    </p>
+    <ul>
+      <li>Modeling 3d parts — draw with extrudes, revolves, and Boolean operations</li>
+      <li>Modeling 2d parts — draw the part as a single section, and export; use 3d assembly to verify fit</li>
+      <li>Modeling 3d-printed parts — export the STL or other triangle mesh expected by most slicers</li>
+      <li>Preparing 2D CAM data — export 2d vector art for a waterjet machine or laser cutter</li>
+      <li>Mechanism design — use the constraint solver to simulate planar or spatial linkages</li>
+      <li>Plane and solid geometry — replace hand-solved trigonometry with a live dimensioned drawing</li>
+    </ul>
+  </description>
+  <url type="homepage">https://solvespace.com</url>
+  <url type="bugtracker">https://github.com/solvespace/solvespace/issues</url>
+
+  <launchable type="desktop-id">@DESKTOP_FILE_NAME@</launchable>
+  <provides>
+    <mediatype>application/x-solvespace</mediatype>
+  </provides>
+
+  <content_rating type="oars-1.0" />
+
+  <releases>
+    <release version="3.0" date="2021-04-18" type="stable">
+      <description>
+        <p>Major new stable release. Includes new intersection boolean operation,
+        new types of groups, solid model suppression, usability improvements
+        (especially regarding redundant constraints and automatic constraints),
+        and more. Also includes performance and scalability improvements.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v3.0</url>
+    </release>
+
+    <release version="3.0~rc2" date="2021-01-17" type="development">
+      <description>
+        <p>Second release candidate for the 3.0 stable release.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v3.0.rc2</url>
+    </release>
+
+    <release version="3.0~rc1" date="2020-11-18" type="development">
+      <description>
+        <p>First release candidate for the 3.0 stable release.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v3.0.rc1</url>
+    </release>
+
+    <release version="2.3" date="2016-12-23" type="stable">
+      <description>
+        <p>Bug-fix release in the 2.x series, fixing some crashes.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v2.3</url>
+    </release>
+
+    <release version="2.2" date="2016-10-16" type="stable">
+      <description>
+        <p>Bug-fix release, including performance improvements.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v2.2</url>
+    </release>
+
+    <release version="2.1" date="2016-06-11" type="stable">
+      <description>
+        <p>Introduced *nix compatibility, internationalization, technical drawing mode, improved import and export, and other features and fixes.</p>
+      </description>
+      <url>https://github.com/solvespace/solvespace/releases/tag/v2.1</url>
+    </release>
+  </releases>
+
+</component>
diff --git a/res/freedesktop/solvespace-16x16.xpm b/res/freedesktop/solvespace-16x16.xpm
deleted file mode 100644 (file)
index 3cd0662..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* XPM */
-static char *solvespace_16x16[] = {
-/* columns rows colors chars-per-pixel */
-"16 16 5 1 ",
-"  c black",
-". c #1ED500",
-"X c #DE00D6",
-"o c #CBCBCB",
-"O c None",
-/* pixels */
-"OOO OOOOOOOOOOOO",
-"OOO OOOOOOOOOOOO",
-"OOO OOOOOOOOOOOO",
-"OOO OOOOOXOOOOOO",
-"OOO OOOOOXoOOOOO",
-"OOO OOOOOXoOOOOO",
-"OOO OOOOOXoOOOOO",
-"OOO OOOOOXoOOOOO",
-"OOO OOOOOXoOOOOO",
-"OOO OOXXXXXXXOOO",
-"OOO OOOoooooooOO",
-"OO...OOOOOOOOOOO",
-"  ...           ",
-"OO...OOOOOOOOOOO",
-"OOO OOOOOOOOOOOO",
-"OOO OOOOOOOOOOOO"
-};
diff --git a/res/freedesktop/solvespace-24x24.xpm b/res/freedesktop/solvespace-24x24.xpm
deleted file mode 100644 (file)
index 9d1c02e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* XPM */
-static char *solvespace_24x24[] = {
-/* columns rows colors chars-per-pixel */
-"24 24 5 1 ",
-"  c black",
-". c #1ED500",
-"X c #DE00D6",
-"o c #CBCBCB",
-"O c None",
-/* pixels */
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOXOOOOOOOOOO",
-"OOOOOOO OOOOOXoOOOOOOOOO",
-"OOOOOOO OOOOOXoOOOOOOOOO",
-"OOOOOOO OOOOOXoOOOOOOOOO",
-"OOOOOOO OOOOOXoOOOOOOOOO",
-"OOOOOOO OOOOOXoOOOOOOOOO",
-"OOOOOOO OOXXXXXXXOOOOOOO",
-"OOOOOOO OOOoooooooOOOOOO",
-"OOOOOO...OOOOOOOOOOOOOOO",
-"OOOO  ...           OOOO",
-"OOOOOO...OOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOOOOOOOOOOOO",
-"OOOOOOO OOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOO"
-};
diff --git a/res/freedesktop/solvespace-32x32.xpm b/res/freedesktop/solvespace-32x32.xpm
deleted file mode 100644 (file)
index 0d7c598..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* XPM */
-static char *solvespace_32x32[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 5 1 ",
-"  c black",
-". c #1ED500",
-"X c #DE00D6",
-"o c #CBCBCB",
-"O c None",
-/* pixels */
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOXXoOOOOOOOOOOOO",
-"OOOOOO  OOOOXXXXXXXXXXXXOOOOOOOO",
-"OOOOOO  OOOOXXXXXXXXXXXXOOOOOOOO",
-"OOOOOO  OOOOOooooooooooooOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
-"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
-"    ......                      ",
-"    ......                      ",
-"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
-"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOO  OOOOOOOOOOOOOOOOOOOOOOOO"
-};
diff --git a/res/freedesktop/solvespace-48x48.xpm b/res/freedesktop/solvespace-48x48.xpm
deleted file mode 100644 (file)
index c5adf53..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* XPM */
-static char *solvespace_48x48[] = {
-/* columns rows colors chars-per-pixel */
-"48 48 5 1 ",
-"  c black",
-". c #1ED500",
-"X c #DE00D6",
-"o c #CBCBCB",
-"O c None",
-/* pixels */
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOXXXXXXXXXXXXOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOXXXXXXXXXXXXOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOooooooooooooOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOO    ......                      OOOOOOOO",
-"OOOOOOOO    ......                      OOOOOOOO",
-"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOO  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
-"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
-};
index b16ccf44e858f5da7f3a65b29748cc33f1c3f45c..c80b67ad67fa712b7e0853ec0310467fc60df09e 100644 (file)
@@ -6,5 +6,5 @@ Exec=${CMAKE_INSTALL_FULL_BINDIR}/solvespace
 MimeType=application/x-solvespace
 Icon=com.solvespace.SolveSpace
 Type=Application
-Categories=Graphics
+Categories=Graphics;3DGraphics;Engineering;
 Keywords=parametric;cad;2d;3d;
index 8441258c9110c92add7ba71e320748bf91454c10..da0dda13a53b3b629abe45c3a3bf1c80ac8d61b3 100644 (file)
@@ -6,5 +6,5 @@ Exec=solvespace
 MimeType=application/x-solvespace
 Icon=${SNAP}/meta/icons/hicolor/scalable/apps/snap.solvespace.svg
 Type=Application
-Categories=Graphics
+Categories=Graphics;3DGraphics;Engineering;
 Keywords=parametric;cad;2d;3d;
index 8c6fb24a934bb3c6fb672be39dc7ce4658d4d4df..87e6863c9641f01aa1028cbf8d3b15c06aeedf1f 100644 (file)
@@ -6,5 +6,5 @@ Exec=${CMAKE_INSTALL_FULL_BINDIR}/solvespace
 MimeType=application/x-solvespace
 Icon=solvespace
 Type=Application
-Categories=Graphics
+Categories=Graphics;3DGraphics;Engineering;
 Keywords=parametric;cad;2d;3d;
index f70252a937e1bac714ac402019680cd90484b7b6..8b82ba3da047060117606a1b535682569d037374 100644 (file)
Binary files a/res/icons/graphics-window/angle.png and b/res/icons/graphics-window/angle.png differ
index 807b7366dfa57d8af5a994b28430fb41a7f74360..0acded45c3fe11d494cf9e0da7b4ba9e9d4937b9 100644 (file)
Binary files a/res/icons/graphics-window/arc.png and b/res/icons/graphics-window/arc.png differ
index 4dad1f72ba70f5c7a6097bd6b8b746c276abde67..8436dcdd8b2e89843478fce4f060f5efc32646bd 100644 (file)
Binary files a/res/icons/graphics-window/assemble.png and b/res/icons/graphics-window/assemble.png differ
index 9d2c240a471ac4f5277ad1c66291734fdc207a8b..fd7d438a4fcc32ce750599b5f070105ecf930dc1 100644 (file)
Binary files a/res/icons/graphics-window/bezier.png and b/res/icons/graphics-window/bezier.png differ
index c176b44042d971ccc273a2ac7350ab25716f3573..6ec2c83fbcd10355bf8a67d8204062efd8e487fa 100644 (file)
Binary files a/res/icons/graphics-window/circle.png and b/res/icons/graphics-window/circle.png differ
index 35ddcb274ff9113bfaca088234a5e6c7ac76b1d5..6f48aedefec91ee1c151344e7bdd01d63c000c6a 100644 (file)
Binary files a/res/icons/graphics-window/construction.png and b/res/icons/graphics-window/construction.png differ
index 6037aed0f7c5cf33748e6540cd399a340777ae7a..ba9053aad7bc5a68b1f2b43109f4e1cad9e4d17b 100644 (file)
Binary files a/res/icons/graphics-window/equal.png and b/res/icons/graphics-window/equal.png differ
index 5b57a0eb135c9994bb9d025c5f89f48c7d8fd705..a8eb88bccda1dcf6d60e61e88e778f17960d1698 100644 (file)
Binary files a/res/icons/graphics-window/extrude.png and b/res/icons/graphics-window/extrude.png differ
index 4b2cda68d5138d636ffe3af605bf3ad5fbb696a0..ac4f50962444c828f2033862f633ecfb84a29ded 100644 (file)
Binary files a/res/icons/graphics-window/helix.png and b/res/icons/graphics-window/helix.png differ
index dc94540ac88d213bf9f41b8bb2ebe8ec0e7c4891..3c23d67767d4529ba4b8f26c81766a99af2480c0 100644 (file)
Binary files a/res/icons/graphics-window/horiz.png and b/res/icons/graphics-window/horiz.png differ
index d652d8e77c4297cc57816378acc0b9fa50ac3429..5df953a7c09d2c0a8ea29250747fadbf72e7b89f 100644 (file)
Binary files a/res/icons/graphics-window/image.png and b/res/icons/graphics-window/image.png differ
index bad460f0dba37b2fd6fccfe0a6d4bfce808f1876..bf395f62876a4a7a76b8c450dd76da2782907f17 100644 (file)
Binary files a/res/icons/graphics-window/in3d.png and b/res/icons/graphics-window/in3d.png differ
index 8cee0583c28f0637c4a6c75a0847e021bb7ee696..cb91631b2b7def64147005c0dba90b65a294f899 100644 (file)
Binary files a/res/icons/graphics-window/lathe.png and b/res/icons/graphics-window/lathe.png differ
index b48715e094ccd65dd166f3fa9a61237624c5f752..552c87c6243f2cb62c39fdf7ecae150caad119ed 100644 (file)
Binary files a/res/icons/graphics-window/length.png and b/res/icons/graphics-window/length.png differ
index b99a0d86c52e1e6be5690af65d334924fd9bb223..356130f98bb798eefc0b3e254ee20d0a95648835 100644 (file)
Binary files a/res/icons/graphics-window/line.png and b/res/icons/graphics-window/line.png differ
index fbf6ff30fa5f3a46bbc3ea80b5b7ba2818b81cee..66642a3302170ff9e04d9a81da7bf29a8211c54f 100644 (file)
Binary files a/res/icons/graphics-window/ontoworkplane.png and b/res/icons/graphics-window/ontoworkplane.png differ
index b2ea5a95d359ee2f477b66eba6d86e30bfd7550f..a5577760f672e5021f77e0bd25ee7ccdb5fcff7b 100644 (file)
Binary files a/res/icons/graphics-window/other-supp.png and b/res/icons/graphics-window/other-supp.png differ
index fe89e2f100c33ae3ed352d0e318d0e502cfb2226..5f76105d102810e94ba955120677b3e076c75a3d 100644 (file)
Binary files a/res/icons/graphics-window/parallel.png and b/res/icons/graphics-window/parallel.png differ
index e9bf5d5f7493358a181cfa1c82c66970aced3094..2127714370015ab1d9379f767aef3e86e0a4641b 100644 (file)
Binary files a/res/icons/graphics-window/perpendicular.png and b/res/icons/graphics-window/perpendicular.png differ
index d50ffffbd8860b240712f764345313f202ca4471..a1a56660c3454a37e47343c6aba8a54a5f65f02b 100644 (file)
Binary files a/res/icons/graphics-window/point.png and b/res/icons/graphics-window/point.png differ
index d0f6b674c388038a36a5d2c784567ce0c01803f4..0fa950659253f0c27bb6e3684b10a7e17b4298d9 100644 (file)
Binary files a/res/icons/graphics-window/pointonx.png and b/res/icons/graphics-window/pointonx.png differ
index d36dc4c5c71a07e3b248cefa6eb354e95725e485..3f9ea7cceea3cda0495728c48f8e3125e6d0bdb3 100644 (file)
Binary files a/res/icons/graphics-window/rectangle.png and b/res/icons/graphics-window/rectangle.png differ
index 19f3b88a7c512fb185d6b3f224ef7a596617ad9d..6bc2894fe4f34d397a3219304311c79f2e370c83 100644 (file)
Binary files a/res/icons/graphics-window/ref.png and b/res/icons/graphics-window/ref.png differ
index 0cef0fa669102188757aabc5750b5c0fe9b5b5f1..0569907cd4b1576e46e874e9845573e41d6b2c47 100644 (file)
Binary files a/res/icons/graphics-window/revolve.png and b/res/icons/graphics-window/revolve.png differ
index 850d2da8996482586e1c086848a01e947a6ddbb6..7223d0cc7326f971b86d8f83ab3ac2f0c2064ff9 100644 (file)
Binary files a/res/icons/graphics-window/same-orientation.png and b/res/icons/graphics-window/same-orientation.png differ
index 0a73b6b56ba64ba17089c01e082778a3b2da9ebf..d15a0d32cc0c2d7399904e8d3da5ffcd6ba630e3 100644 (file)
Binary files a/res/icons/graphics-window/sketch-in-3d.png and b/res/icons/graphics-window/sketch-in-3d.png differ
index c52c40cf357b6c521abe7689fdd2f5d27bfbe025..30c99bebe65d34b52f4dcaf64e257cee5c590acc 100644 (file)
Binary files a/res/icons/graphics-window/sketch-in-plane.png and b/res/icons/graphics-window/sketch-in-plane.png differ
index 22969f65fbc41248dac0cc9cea78066c32e7a7cb..a64eae44c50606cf5e78db2df0d5516f3fb60066 100644 (file)
Binary files a/res/icons/graphics-window/step-rotate.png and b/res/icons/graphics-window/step-rotate.png differ
index 2901f9e52b4239d3d0adddb1500e484f38453212..493f85335b241e1ddd9835a475418d12dc88fd33 100644 (file)
Binary files a/res/icons/graphics-window/step-translate.png and b/res/icons/graphics-window/step-translate.png differ
index e6e80ebe4b71647854ce2802c6e8e6b9ad2b58d4..41926842b541e64e58bf9f8a03bc4a39be0ce39b 100644 (file)
Binary files a/res/icons/graphics-window/symmetric.png and b/res/icons/graphics-window/symmetric.png differ
index d9dc40ac631cd3beedfed2da1ebe7fd5989a002f..88feddbd159521c8ccc2c39043f1d55f99a8ec7a 100644 (file)
Binary files a/res/icons/graphics-window/tangent-arc.png and b/res/icons/graphics-window/tangent-arc.png differ
index 8923573ab0cbfc1e44c44f7bf6a95aaca7415f59..886a80aa376d9134a60665f02743d895f62e0a3e 100644 (file)
Binary files a/res/icons/graphics-window/text.png and b/res/icons/graphics-window/text.png differ
index 248e448ce7ef3c1584f872da0554d748607f6db7..de11e17aa429a0ef73fea5132b127642e7fd05ad 100644 (file)
Binary files a/res/icons/graphics-window/trim.png and b/res/icons/graphics-window/trim.png differ
index f137913c954b8b4a7f336bbff83c220e914a6ba8..996b191ebc904467d8effccb0b398e9b2602cd7f 100644 (file)
Binary files a/res/icons/graphics-window/vert.png and b/res/icons/graphics-window/vert.png differ
index bc1a7178a23da7acf244a22f5b9a4a0a94562a5f..431ed754bba53411d5a12ba1c6f2a49e52ef2456 100644 (file)
Binary files a/res/icons/text-window/constraint.png and b/res/icons/text-window/constraint.png differ
index 35ddcb274ff9113bfaca088234a5e6c7ac76b1d5..0ecc9a130513126f01c970193aa6bc9418aa7b87 100644 (file)
Binary files a/res/icons/text-window/construction.png and b/res/icons/text-window/construction.png differ
index fcfd009ffde0fa487f4a55546c2a176e10c6dce8..f428de17b4d6dbc7e51dd26e5a7e83d04a118753 100644 (file)
Binary files a/res/icons/text-window/edges.png and b/res/icons/text-window/edges.png differ
index e92cd5dceda3f3ffba76b27ff11bb682b8c24a01..57345dff48ba9b1a5453960c9a5a27e2a463ee11 100644 (file)
Binary files a/res/icons/text-window/faces.png and b/res/icons/text-window/faces.png differ
index efc6278a2084f547d8206a831d8604872f37374e..260b083f62f8bac2ad6a6523648e2dcd80bc6a88 100644 (file)
Binary files a/res/icons/text-window/mesh.png and b/res/icons/text-window/mesh.png differ
index c87ea5176006bc3823ec3fbad8778c420fe89134..95a83391523c31ad18a202ee23a694169270356f 100644 (file)
Binary files a/res/icons/text-window/normal.png and b/res/icons/text-window/normal.png differ
index 5ab4f82fbdf14b1145951f7597361a8157fbc840..ed353012d914379c6715829aab23081a899dd006 100644 (file)
Binary files a/res/icons/text-window/occluded-invisible.png and b/res/icons/text-window/occluded-invisible.png differ
index 6d7a33f221f038d68881cacea2c318a0cea36dcb..04ee458eb10f83bbbca7225b621369c45694e507 100644 (file)
Binary files a/res/icons/text-window/occluded-stippled.png and b/res/icons/text-window/occluded-stippled.png differ
index 2ccd73e6c878d72326c415f20f7bb17ca3415603..23415c300565dc98e5e1b14c6587b8c7827edaac 100644 (file)
Binary files a/res/icons/text-window/occluded-visible.png and b/res/icons/text-window/occluded-visible.png differ
index 2c07fba05227a1b74185efdcf65c7561be452e65..f947ec7fea5375c12135b163d20de2de9c9b83a4 100644 (file)
Binary files a/res/icons/text-window/outlines.png and b/res/icons/text-window/outlines.png differ
index 421688105dbb6739e62266c82ae3c4894d3a29a2..a1a56660c3454a37e47343c6aba8a54a5f65f02b 100644 (file)
Binary files a/res/icons/text-window/point.png and b/res/icons/text-window/point.png differ
index 7df689757b247f538a10c5b203b22311c61a3d74..8e293cd504e1917b1e8c760a6601090956275819 100644 (file)
Binary files a/res/icons/text-window/workplane.png and b/res/icons/text-window/workplane.png differ
index 0f4fab16b608f77cb01eae4bf20f1673dff84951..d94e2c0410d695dc84c85f7fd73e03182488676b 100644 (file)
@@ -3,6 +3,8 @@
 de-DE,0407,Deutsch
 en-US,0409,English (US)
 fr-FR,040C,Français
+es-AR,2C0A,español (AR)
 ru-RU,0419,Русский
+tr-TR,041F,Türkçe
 uk-UA,0422,Українська
 zh-CN,0804,简体中文
index 9222a1dc31345de9d8fa57d2de3dd3367a524516..11d77fac88fb697ffc772f6d7cd2b885c9773cd9 100644 (file)
@@ -6,18 +6,18 @@ msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
-"PO-Revision-Date: 2018-07-19 06:55+0000\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2022-04-30 16:44+0200\n"
 "Last-Translator: Reini Urban <rurban@cpan.org>\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"
-"X-Generator: Zanata 4.5.0\n"
-"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"X-Generator: Poedit 2.4.2\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
@@ -26,29 +26,29 @@ msgstr ""
 "Ausschneiden, Einfügen und Kopieren sind nur in einer Arbeitsebene "
 "zulässig.\n"
 "\n"
-"Aktivieren Sie eine mit Skizze -> In Arbeitsebene"
+"Aktivieren Sie eine mit \"Skizze -> In Arbeitsebene\"."
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr "Zwischenablage ist leer; es gibt nichts einzufügen."
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr "Die Anzahl der einzufügenden Kopien muss mind. 1 sein."
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr "Maßstab kann nicht Null sein."
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr "Wählen Sie einen Punkt, um den Drehmittelpunkt zu definieren."
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr "Wählen Sie zwei Punkte, um den Verschiebungsvektor zu definieren."
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
@@ -56,25 +56,25 @@ msgstr ""
 "Die Transformation ist die Identität. Alle Kopien werden deckungsgleich "
 "übereinanderliegen."
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr ""
 "Zuviele Objekte zum Einfügen; teilen Sie diese in kleinere "
 "Einfügeoperationen auf."
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr "Es ist keine Arbeitsebene aktiv."
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr "Ungültiges Format: geben Sie Koordinaten als x, y, z an"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr "Ungültiges Format: geben Sie Farben als r, g, b an"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
@@ -82,25 +82,25 @@ msgstr ""
 "Der Perspektivfaktor wird sich nicht auswirken, bis Sie Ansicht -> "
 "Perspektive Projektion aktivieren."
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr "Geben Sie 0 bis %d Ziffern nach dem Dezimalzeichen an."
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr "Der Exportmaßstab darf nicht Null sein!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr "Der Werkzeugradialabstand darf nicht negativ sein!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr ""
 "Ungültiger Wert: Interval für automatisches Speichern muss positiv sein"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr "Ungültiges Format: geben Sie das Interval in ganzen Minuten an"
 
@@ -171,141 +171,161 @@ msgstr "Längenverhältnis"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr "Bogen-Bogen-Längenverhältnis"
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr "Bogen-Linien-Längenverhältnis"
+
+#: constraint.cpp:27
+msgctxt "constr-name"
 msgid "length-difference"
 msgstr "Längendifferenz"
 
-#: constraint.cpp:26
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr "Bogen-Bogen-Längendifferenz"
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr "Bogen-Linien-Längendifferenz"
+
+#: constraint.cpp:30
 msgctxt "constr-name"
 msgid "symmetric"
 msgstr "Symmetrisch"
 
-#: constraint.cpp:27
+#: constraint.cpp:31
 msgctxt "constr-name"
 msgid "symmetric-h"
 msgstr "Symmetrisch-H"
 
-#: constraint.cpp:28
+#: constraint.cpp:32
 msgctxt "constr-name"
 msgid "symmetric-v"
 msgstr "Symmetrisch-V"
 
-#: constraint.cpp:29
+#: constraint.cpp:33
 msgctxt "constr-name"
 msgid "symmetric-line"
 msgstr "Symmetrisch-Linie"
 
-#: constraint.cpp:30
+#: constraint.cpp:34
 msgctxt "constr-name"
 msgid "at-midpoint"
 msgstr "auf-Mittelpunkt"
 
-#: constraint.cpp:31
+#: constraint.cpp:35
 msgctxt "constr-name"
 msgid "horizontal"
 msgstr "Horizontal"
 
-#: constraint.cpp:32
+#: constraint.cpp:36
 msgctxt "constr-name"
 msgid "vertical"
 msgstr "Vertikal"
 
-#: constraint.cpp:33
+#: constraint.cpp:37
 msgctxt "constr-name"
 msgid "diameter"
 msgstr "Durchmesser"
 
-#: constraint.cpp:34
+#: constraint.cpp:38
 msgctxt "constr-name"
 msgid "pt-on-circle"
 msgstr "Pkt-auf-Kreis"
 
-#: constraint.cpp:35
+#: constraint.cpp:39
 msgctxt "constr-name"
 msgid "same-orientation"
 msgstr "gl-Orientierung"
 
-#: constraint.cpp:36
+#: constraint.cpp:40
 msgctxt "constr-name"
 msgid "angle"
 msgstr "Winkel"
 
-#: constraint.cpp:37
+#: constraint.cpp:41
 msgctxt "constr-name"
 msgid "parallel"
 msgstr "Parallel"
 
-#: constraint.cpp:38
+#: constraint.cpp:42
 msgctxt "constr-name"
 msgid "arc-line-tangent"
 msgstr "Bogen-Linie-Tangente"
 
-#: constraint.cpp:39
+#: constraint.cpp:43
 msgctxt "constr-name"
 msgid "cubic-line-tangent"
 msgstr "Kub-Linie-Tangente"
 
-#: constraint.cpp:40
+#: constraint.cpp:44
 msgctxt "constr-name"
 msgid "curve-curve-tangent"
 msgstr "Kurve-Kurve-Tangente"
 
-#: constraint.cpp:41
+#: constraint.cpp:45
 msgctxt "constr-name"
 msgid "perpendicular"
 msgstr "Rechtwinklig"
 
-#: constraint.cpp:42
+#: constraint.cpp:46
 msgctxt "constr-name"
 msgid "eq-radius"
 msgstr "gl-Radius"
 
-#: constraint.cpp:43
+#: constraint.cpp:47
 msgctxt "constr-name"
 msgid "eq-angle"
 msgstr "gl-Winkel"
 
-#: constraint.cpp:44
+#: constraint.cpp:48
 msgctxt "constr-name"
 msgid "eq-line-len-arc-len"
 msgstr "gl-Linie-Länge-Bogen-Länge"
 
-#: constraint.cpp:45
+#: constraint.cpp:49
 msgctxt "constr-name"
 msgid "lock-where-dragged"
 msgstr "Fix-an-Position"
 
-#: constraint.cpp:46
+#: constraint.cpp:50
 msgctxt "constr-name"
 msgid "comment"
 msgstr "Kommentar"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
 msgstr ""
 "Die Bogentangente und das Liniensegment müssen einen gemeinsamen Endpunkt "
 "haben. Schränken Sie mit \"Einschränkung / Auf Punkt\" ein, bevor Sie die "
-"Tangente einschränken. -> Sc"
+"Tangente einschränken."
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
 msgstr ""
 "Die Kurventangente und das Liniensegment müssen einen gemeinsamen Endpunkt "
 "haben. Schränken Sie mit \"Einschränkung / Auf Punkt\" ein, bevor Sie die "
-"Tangente einschränken. -> Sc"
+"Tangente einschränken."
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
 msgstr ""
 "Die Kurven müssen einen gemeinsamen Endpunkt haben. Schränken Sie mit "
-"\"Einschränkung / Auf Punkt\" ein, bevor Sie die Tangente einschränken. -> Sc"
+"\"Einschränkung / Auf Punkt\" ein, bevor Sie die Tangente einschränken."
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -329,7 +349,7 @@ msgstr ""
 "    * eine Seitenfläche und ein Punkt [minimaler Abstand]\n"
 "    * ein Kreis oder ein Bogen [Durchmesser]\n"
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -349,7 +369,7 @@ msgstr ""
 "    * einen Punkt und einen Kreis oder Bogen [Punkt auf Kurve]\n"
 "    * einen Punkt und eine Seitenfläche [Punkt auf Fläche]\n"
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -380,30 +400,38 @@ msgstr ""
 "    * ein Liniensegment und ein Bogen [Länge des Liniensegments gleich "
 "Bogenlänge]\n"
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 "Ungültige Auswahl für Einschränkung \"Längenverhältnis\". Diese "
 "Einschränkung ist anwendbar auf:\n"
 "\n"
 "    * zwei Liniensegmente\n"
+"    * zwei Bögen\n"
+"    * einen Bogen und ein Liniensegment\n"
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 "Ungültige Auswahl für Einschränkung \"Längendifferenz\". Diese Einschränkung "
 "ist anwendbar auf:\n"
 "\n"
 "    * zwei Liniensegmente\n"
+"    * zwei Bögen\n"
+"    * einen Bogen und ein Liniensegment\n"
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -417,7 +445,7 @@ msgstr ""
 "    * ein Liniensegment und eine Arbeitsebene [Mittelpunkt der Linie auf "
 "Ebene]\n"
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -438,7 +466,7 @@ msgstr ""
 "    * eine Arbeitsebene und zwei Punkte oder ein Liniensegment [symmetrisch "
 "zu Arbeitsebene]\n"
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
@@ -446,7 +474,7 @@ msgstr ""
 "Eine Arbeitsebene muss aktiv sein, um die Symmetrie ohne explizite "
 "Symmetrieebene einzuschränken."
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
@@ -454,7 +482,7 @@ msgstr ""
 "Aktivieren Sie eine Arbeitsebene (mit Skizze -> In Arbeitsebene), bevor Sie "
 "horizontal oder vertikal einschränken."
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -468,7 +496,7 @@ msgstr ""
 "    * zwei Punkte\n"
 "    * ein Liniensegment\n"
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
@@ -480,15 +508,15 @@ msgstr ""
 "\n"
 "    * zwei Normale\n"
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr "Sie müssen einen eingeschränkten Winkel auswählen."
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr "Sie müssen eine Einschränkung mit zugeordneter Kennzeichnung angeben."
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -503,12 +531,12 @@ msgstr ""
 "    * ein Liniensegment und eine Normale\n"
 "    * zwei Normale\n"
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr ""
 "Die Kurven-Kurven-Tangente muss in der Arbeitsebene eingeschränkt werden."
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -527,7 +555,7 @@ msgstr ""
 "    * zwei Liniensegmente, Bögen oder Beziers mit gemeinsamem Endpunkt "
 "[Tangente]\n"
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -542,7 +570,7 @@ msgstr ""
 "    * ein Liniensegment und eine Normale\n"
 "    * zwei Normale\n"
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
@@ -554,7 +582,11 @@ msgstr ""
 "\n"
 "    * einen Punkt\n"
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "NEUER KOMMENTAR -- DOPPELKLICKEN ZUM BEARBEITEN"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr "Klicken Sie auf die Mitte des Kommentartextes"
 
@@ -564,7 +596,7 @@ msgid ""
 "2d View to export bare lines and curves."
 msgstr ""
 "Kein Festkörper vorhanden; zeichnen Sie eines mit Extrusionen und Drehungen, "
-"oder exportieren Sie bloße Linien und Kurven mit \"2D-Ansicht exportieren\""
+"oder exportieren Sie bloße Linien und Kurven mit \"2D-Ansicht exportieren\"."
 
 #: export.cpp:61
 msgid ""
@@ -583,26 +615,26 @@ msgstr ""
 "    * einen Punkt und zwei Liniensegmente [Schnittebene durch Punkt und "
 "parallel zu Linien]\n"
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
 msgstr "Das Netz der aktiven Gruppe ist leer; es gibt nichts zu exportieren."
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr "Freihandlinien wurden mit durchgehenden Linien ersetzt"
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr "Zickzacklinien wurden mit durchgehenden Linien ersetzt"
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
 "Teile der Zeichnung haben keine Entsprechung in DXF und wurden nicht "
 "exportiert:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
@@ -619,7 +651,11 @@ msgctxt "group-name"
 msgid "#references"
 msgstr "#Referenzen"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "Die Datei ist leer. Es kann beschädigt sein."
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
@@ -627,18 +663,18 @@ msgstr ""
 "Nicht erkannte Daten in der Datei. Diese Datei könnte beschädigt sein oder "
 "von einer neueren Version des Programms stammen."
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr "Fehlende Datei"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
 msgstr "Die verlinkte Datei “%s” fehlt."
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -650,17 +686,17 @@ msgstr ""
 "Falls Sie ablehnen, wird jegliche mit der fehlenden Datei verknüpfte "
 "Geometrie verworfen."
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr "&Ja"
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr "&Nein"
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr "&Abbrechen"
@@ -675,7 +711,7 @@ msgstr "&Neu"
 
 #: graphicswin.cpp:43
 msgid "&Open..."
-msgstr "&Öffnen"
+msgstr "&Öffnen..."
 
 #: graphicswin.cpp:44
 msgid "Open &Recent"
@@ -703,7 +739,7 @@ msgstr "Exportiere 2D-Auswahl…"
 
 #: graphicswin.cpp:51
 msgid "Export 3d &Wireframe..."
-msgstr "Exportiere 3D-Drahtgittermodell"
+msgstr "Exportiere 3D-Drahtgittermodell..."
 
 #: graphicswin.cpp:52
 msgid "Export Triangle &Mesh..."
@@ -834,296 +870,308 @@ msgid "Use &Perspective Projection"
 msgstr "Perspektivische Projektion"
 
 #: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr "Zeige e&xplodierte Ansicht"
+
+#: graphicswin.cpp:98
 msgid "Dimension &Units"
 msgstr "Maßeinheit"
 
-#: graphicswin.cpp:98
+#: graphicswin.cpp:99
 msgid "Dimensions in &Millimeters"
 msgstr "Maße in Millimeter"
 
-#: graphicswin.cpp:99
+#: graphicswin.cpp:100
 msgid "Dimensions in M&eters"
 msgstr "Masse in M&etern"
 
-#: graphicswin.cpp:100
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr "Maße in Zoll"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr "Maße in &Fuß und Inch"
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "Werkzeugleiste anzeigen"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "Attributbrowser anzeigen"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "Vollbildschirm"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "Neue Gruppe"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr "In 3D skizzieren"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr "In neuer Arbeitsebene skizzieren"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "Kopieren und verschieben"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "Kopieren und drehen"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "E&xtrudieren"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
 msgstr "&Helix"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "R&otieren"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
 msgstr "D&rehen"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
-msgstr "Verknüpfen / Zusammensetzen"
+msgstr "Verknüpfen / Zusammensetzen..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr "Letzte verknüpfen"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "&Skizze"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr "In Arbeitsebene"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr "Im 3D-Raum"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "Bezugspunkt"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "Arbeits&ebene"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "&Linie"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "K&onstruktionslinie"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "&Rechteck"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "&Kreis"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "Kreisbogen"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "Kubischer &Bezier-Spline"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr "&Text in Truetype-Font"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr "B&ild"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "Konstruktionselement an/aus"
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "Bogentangente an Punkt"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "Kurven im Schnittpunkt trennen"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "&Einschränkung"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "Abstand / Durchmesser"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "Referenzangabe"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "Winkel"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "Referenzwinkel"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "Komplementärwinkel"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "Referenzangabe ein/aus"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "Horizontal"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "&Vertikal"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "Auf Punkt / Kurve / Ebene"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "Gleicher Abstand / Radius / Winkel"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "Längenverhältnis"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr "Länge / Bogen Verhäl&tnis"
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "Längendifferenz"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr "Länge / Bogen Diff&erenz"
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "Auf &Mittelpunkt"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "Symmetrisch"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "Paral&llel / Tangente"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "Rechtwinklig"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "Gleiche Orientierung"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "Punkt an Position fixieren"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "Kommentar"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "&Analyse"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "&Volumen bestimmen"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "Fläche bestimmen"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "Umfang bestimmen"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "Überlagernde Teile anzeigen"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "Freiliegende Kanten anzeigen"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
 msgstr "Massenmittelpunkt anzeigen"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
 msgstr "&Unterbeschränkte Punkte anzeigen"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "Punkt nachzeichnen"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
-msgstr "Nachzeichnen beenden"
+msgstr "Nachzeichnen beenden..."
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "Schrittgröße…"
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "&Hilfe"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "Sprache"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "&Website / Anleitung"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr "&Gehe zu GitHub commit"
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "Über"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr "(keine vorhergehenden Dateien)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
 msgstr "Datei '%s' existiert nicht."
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr ""
 "Das Raster wird nicht angezeigt, weil keine Arbeitsebene ausgewählt ist."
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -1137,20 +1185,20 @@ msgstr ""
 "Ändern Sie den Faktor für die Perspektivprojektion in der "
 "Konfigurationsmaske. Ein typischer Wert ist ca. 0,3."
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr ""
 "Wählen Sie einen Punkt aus; dieser Punkt wird im Mittelpunkt der "
 "Bildschirmansicht sein."
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr ""
 "Die ausgewählten Objekte teilen keine gemeinsamen Endpunkte mit anderen "
 "Objekten."
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
@@ -1158,7 +1206,7 @@ msgstr ""
 "Für diesen Befehl wählen Sie einen Punkt oder ein anderes Objekt von einem "
 "verknüpften Teil aus, oder aktivieren Sie eine verknüpfte Gruppe."
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
@@ -1167,7 +1215,7 @@ msgstr ""
 "(mit Skizze -> In Arbeitsebene), um die Ebene für das Gitterraster zu "
 "definieren."
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
@@ -1176,13 +1224,13 @@ msgstr ""
 "für Punkte, Textkommentare, oder Einschränkungen mit einer Bezeichnung. Um "
 "eine Linie auf das Raster auszurichten, wählen Sie deren Endpunkte aus."
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 "Es wurde keine Arbeitsebene ausgewählt. Die Standard-Arbeitsebene für diese "
 "Gruppe wird aktiviert."
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
@@ -1192,7 +1240,7 @@ msgstr ""
 "standardmäßige Arbeitsebene. Wählen Sie eine Arbeitsebene aus, oder "
 "erstellen Sie eine Gruppe in einer neuen Arbeitsebene."
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
@@ -1200,48 +1248,48 @@ msgstr ""
 "Ungültige Auswahl für Bogentangente an Punkt. Wählen Sie einen einzelnen "
 "Punkt. Um die Bogenparameter anzugeben, wählen Sie nichts aus."
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr ""
 "Erstellen Sie einen Punkt auf dem Bogen (zeichnet im Gegenuhrzeigersinn)"
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr "Klicken Sie, um einen Bezugspunkt zu platzieren"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr "Klicken Sie auf den ersten Punkt des Liniensegments"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr "Klicken Sie auf den ersten Punkt der Konstruktionslinie"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr "Klicken Sie auf den ersten Punkt der kubischen Linie"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr "Klicken Sie auf den Kreismittelpunkt"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr "Klicken Sie auf den Ursprungspunkt der Arbeitsebene"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr "Klicken Sie auf eine Ecke des Rechtecks"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr "Klicken Sie auf die obere linke Ecke des Texts"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr "Klicken Sie auf die obere linke Ecke des Bilds"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1254,41 +1302,41 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr "Skizze-in-3D"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
-"Ungültige Auswahl für Skizze in neuer Arbeitsebene. Diese Gruppe kann "
+"Ungültige Auswahl für neue Skizze in der Arbeitsebene. Diese Gruppe kann "
 "erstellt werden mit:\n"
 "\n"
-"    * einem Punkt (durch den Punkt, orthogonal zu den Koordinatenachsen)\n"
-"    * einem Punkt und zwei Liniensegmenten (durch den Punkt, parallel zu den "
-"Linien)\n"
-"    * einer Arbeitsebene (Kopie der Arbeitsebene)\n"
+"    * einem Punkt (durch den Punkt, orthogonal zur Koordinatenachse)\n"
+"    * einem Punkt und zwei Linienabschnitten (durch den Punkt, parallel zu "
+"den Linien)\n"
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
 msgstr ""
 "Aktivieren Sie vor der Extrusion eine Arbeitsebene (mit Skizze -> In "
-"Arbeitsebene). Die Skizze wird senkrecht zur Arbeitsebene extrudiert"
+"Arbeitsebene). Die Skizze wird senkrecht zur Arbeitsebene extrudiert."
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr "Extrusion"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr "Rotieren kann nur mit planaren Skizzen ausgeführt werden."
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1303,16 +1351,16 @@ msgstr ""
 "eine Achse parallel zur Linie/Normalen, durch den Punkt)\n"
 "    * einem Liniensegment (Drehung um das Liniensegment)\n"
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr "Drehung"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr "Revolve kann nur mit planaren Skizzen ausgeführt werden."
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1327,16 +1375,16 @@ msgstr ""
 "Achse parallel zu Linie / Normale, durch Punkt)\n"
 "    * einem Liniensegment (gedreht um Liniensegment)\n"
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
 msgstr "Revolve"
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr "Helix kann nur mit planaren Skizzen ausgeführt werden."
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1351,12 +1399,12 @@ msgstr ""
 "Achse parallel zu Linie / Normale, durch Punkt)\n"
 "    * einem Liniensegment (gedreht um Liniensegment)\n"
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
 msgstr "Helix"
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1372,50 +1420,54 @@ msgstr ""
 "    * einem Punkt und einer Linie oder einer Normale (gedreht um eine Achse "
 "durch den Punkt, parallel zur Linie / Normale)\n"
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr "Drehen"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr "Versetzen"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr "unbenannt"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
 msgstr "Kontur nicht geschlossen, oder kein einheitlicher Linientyp!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr "Punkte sind nicht alle koplanar!"
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr "Kontur überschneidet sich selbst!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr "Kante mit Länge Null!"
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr "Text-formatierte STL Dateien werden aktuell nicht unterstützt"
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr "Eine Bogentangente kann nur in einer Arbeitsebene erstellt werden."
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
 msgstr ""
 "Um eine Bogentangente zu erstellen, wählen Sie einen Punkt, in dem sich zwei "
 "nicht-Konstruktionslinien oder -kreise in dieser Gruppe und Arbeitsebene "
-"treffen. "
+"treffen."
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
@@ -1424,17 +1476,17 @@ msgstr ""
 "Radius, oder erstellen Sie die gewünschte Geometrie von Hand mit \"Tangente"
 "\"-Einschränkungen."
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 "Dieses Objekt konnte nicht geteilt werden. Dies geht nur für Linien, Kreise "
 "oder kubische Splines."
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr "Trennen ist nur in einer Arbeitsebene möglich."
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
@@ -1442,109 +1494,109 @@ msgstr ""
 "Wählen Sie zwei Objekte aus, die sich schneiden (z.B. zwei Linien/Kreise/"
 "Bögen, oder eine Linie/Kreis/Bogen und ein Punkt)."
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr "Trennen nicht möglich; keine Überschneidung gefunden."
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "Linientyp zuordnen"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "Kein Linientyp"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "Neu erstellter benutzerdefinierter Linientyp…"
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "Info zu Gruppe"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "Info zu Linientyp"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "Kantenverlauf auswählen"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "Von/zu Referenzangabe wechseln"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "Anderer Komplementärwinkel"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "Auf Raster ausrichten"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "Spline-Punkt löschen"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "Spline-Punkt hinzufügen"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr ""
 "Spline-Punkt kann nicht hinzugefügt werden: maximale Anzahl der Punkte "
 "erreicht."
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "Konstruktionselement an/aus"
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "Einschränkung \"Punkte deckungsgleich\" löschen"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "Ausschneiden"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "Kopieren"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "Alle auswählen"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "Einfügen"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "Einfügen und transformieren…"
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "Löschen"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "Alle deselektieren"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "Aktive deselektieren"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "Zoom an Bildschirm anpassen"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr "Klicken Sie auf den nächsten Punkt der Linie, oder drücken Sie Esc"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1552,15 +1604,15 @@ msgstr ""
 "Ein Rechteck kann nicht in 3D erstellt werden. Aktivieren Sie zuerst eine "
 "Arbeitsebene mit \"Skizze -> In Arbeitsebene\"."
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr "Klicken Sie auf die gegenüberliegende Ecke des Rechtecks"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr "Klicken Sie, um den Radius festzulegen"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1568,23 +1620,23 @@ msgstr ""
 "Ein Kreisbogen kann nicht in 3D erstellt werden. Aktivieren Sie zuerst eine "
 "Arbeitsebene mit \"Skizze -> In Arbeitsebene\"."
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr "Klicken Sie, um einen Punkt zu platzieren"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr ""
 "Klicken Sie auf den nächsten Punkt der kubischen Linie, oder drücken Sie Esc"
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 "Eine Arbeitsebene ist bereits aktiv. Skizzieren Sie in 3D, bevor Sie eine "
 "neue Arbeitsebene erstellen."
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1592,11 +1644,11 @@ msgstr ""
 "Text kann nicht in 3D erstellt werden. Aktivieren Sie zuerst eine "
 "Arbeitsebene mit \"Skizze -> In Arbeitsebene\"."
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
 msgstr "Klicken Sie auf die untere rechte Ecke des Texts"
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1604,194 +1656,200 @@ msgstr ""
 "Das Bild kann nicht in 3D erstellt werden. Aktivieren Sie zuerst eine "
 "Arbeitsebene mit \"Skizze -> In Arbeitsebene\"."
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr "NEUER KOMMENTAR -- DOPPELKLICKEN ZUM BEARBEITEN"
-
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
 msgstr "SolveSpace-Modelle"
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr "ALLE"
+
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
 msgstr "IDF Leiterplatte"
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr "STL-Dreiecks-Netz"
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr "PNG-Datei"
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr "STL-Netz"
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr "Wavefront OBJ-Netz"
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
 msgstr "Three.js-kompatibles Netz, mit Ansicht"
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr "Three.js-kompatibles Netz, nur Netz"
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
 msgstr "VRML Textdatei"
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr "STEP-Datei"
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr "PDF-Datei"
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr "Eingebettetes Postscript"
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr "Skalierbare Vektorgrafik"
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr "DXF-Datei (AutoCAD 2007)"
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr "HPGL-Datei"
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr "G-Code"
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr "AutoCAD DXF- und DWG-Dateien"
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr "Werte durch Komma getrennt (CSV)"
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr "unbenannt"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr "Datei speichern"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr "Datei öffnen"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr "_Abbrechen"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr "_Speichern"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
 msgstr "_Öffnen"
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr "Automatische Sicherungsdatei verfügbar"
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
 msgstr "Eine automatische Sicherung ist für diese Skizze verfügbar."
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
 msgstr "Wollen Sie die automatische Sicherungsdatei stattdessen laden?"
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
 msgstr "AutoDatei &öffnen"
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
 msgstr "&Nicht laden"
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr "Geänderte Datei"
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
 msgstr "Wollen Sie die Änderungen an der Skizze “%s” sichern?"
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
 msgstr "Wollen Sie die Änderungen an der Skizze sichern?"
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
 msgstr "Ihre Änderungen werden verworfen, wenn sie nicht abgespeichert werden."
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
 msgstr "&Sichern"
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
 msgstr "&Verwerfen"
 
 # solvespace.cpp:557
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr "(Neue Skizze)"
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr "Attribut-Browser"
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
@@ -1801,7 +1859,7 @@ msgstr ""
 "wahrscheinlich nicht. Verstecken Sie sie in dem auf den Link oben im "
 "Textfenster klicken."
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
@@ -1810,23 +1868,23 @@ msgstr ""
 "Kann den Dateityp der Datei '%s' nicht auf Grund der Dateierweiterung "
 "erkennen. Versuchen Sie .dxf oder .dwg."
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
 msgstr ""
 "Die Einschränkung muss einen Namen haben, und darf keine "
 "Referenzdimensionierung sein."
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr ""
 "Falsche Auswahl für die Schrittdimensionierung. Wählen Sie eine "
 "Einschränkung."
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr "Der Zusammenbau funktioniert, gut."
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
@@ -1837,7 +1895,7 @@ msgstr ""
 "\n"
 "    %s"
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1850,7 +1908,7 @@ msgstr ""
 "\n"
 "    %s"
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1862,7 +1920,7 @@ msgstr ""
 "Gekrümmte Flächen wurden als Dreiecksnetz angenähert.\n"
 "Das verursacht Fehler, typischerweise um 1%."
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1879,7 +1937,7 @@ msgstr ""
 "Kurven wurden als gerade Linienstücke angenähert.\n"
 "Das verursacht Fehler, typischerweise um 1%%."
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
@@ -1887,7 +1945,7 @@ msgstr ""
 "Diese Gruppe beinhaltet keine korrekt geschlossene 2D Fläche. Sie ist offen, "
 "nicht koplanar, oder überschneidet sich selbst."
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1904,7 +1962,7 @@ msgstr ""
 "Kurven wurden als gerade Linienstücke angenähert.\n"
 "Das verursacht Fehler, typischerweise um 1%%."
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1921,36 +1979,36 @@ msgstr ""
 "Kurven wurden als gerade Linienstücke angenähert.\n"
 "Das verursacht Fehler, typischerweise um 1%%."
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr "Falsche Auswahl für Umfang. Wähle Liniensegmente, Bögen und Kurven."
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
 msgstr "Falsche Auswahl für Punkt nachzeichnen. Wähle einen einzelnen Punkt."
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
 msgstr "Konnte '%s' nicht schreiben"
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
 msgstr "Das Netz schneidet sich selbst: Falsch, ungültig."
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
 msgstr "Das Netz schneidet sich nicht: Gut, gültig."
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
 msgstr "Das Netz hat lose Kanten: Falsch, ungültig."
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
 msgstr "Das Netz hat keine lose Kanten: Gut, gültig."
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1961,7 +2019,7 @@ msgstr ""
 "\n"
 "Das Modell hat %d Dreiecke, von %d Flächen."
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1976,7 +2034,7 @@ msgstr ""
 "\n"
 "Keine problematischen Kanten, gut.%s"
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1991,7 +2049,7 @@ msgstr ""
 "\n"
 "%d problematische Kanten, schlecht.%s"
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -2021,7 +2079,7 @@ msgstr ""
 "\n"
 "© 2008-%d Jonathan Westhues und andere.\n"
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
@@ -2030,27 +2088,27 @@ msgstr ""
 "Objekt abgeleitet wurde. Versuchen Sie, dem übergeordneten Objekt einen Typ "
 "zuzuordnen."
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
-msgstr "Name des Linientyps kann nicht leer sein."
+msgstr "Name des Linientyps kann nicht leer sein"
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr "Nicht weniger als 1 Wiederholung möglich."
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr "Nicht mehr als 999 Wiederholungen möglich."
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
-msgstr "Der Name der Gruppe darf nicht leer sein."
+msgstr "Der Name der Gruppe darf nicht leer sein"
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr "Durchsichtigkeit muss zwischen Null und Eins sein."
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr "Radius darf nicht null oder negativ sein."
 
@@ -2206,14 +2264,58 @@ msgctxt "button"
 msgid "&OK"
 msgstr "&OK"
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr "Der Maßstab kann nicht Null oder negativ sein."
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr "Ungültiges Format: geben Sie x, y, z ein"
 
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Ungültige Auswahl für Einschränkung \"Längenverhältnis\". Diese "
+#~ "Einschränkung ist anwendbar auf:\n"
+#~ "\n"
+#~ "    * zwei Liniensegmente\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Ungültige Auswahl für Einschränkung \"Längendifferenz\". Diese "
+#~ "Einschränkung ist anwendbar auf:\n"
+#~ "\n"
+#~ "    * zwei Liniensegmente\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "Längenverhältnis"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "Längendifferenz"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Ungültige Auswahl für Skizze in neuer Arbeitsebene. Diese Gruppe kann "
+#~ "erstellt werden mit:\n"
+#~ "\n"
+#~ "    * einem Punkt (durch den Punkt, orthogonal zu den Koordinatenachsen)\n"
+#~ "    * einem Punkt und zwei Liniensegmenten (durch den Punkt, parallel zu "
+#~ "den Linien)\n"
+#~ "    * einer Arbeitsebene (Kopie der Arbeitsebene)\n"
+
 #~ msgctxt "file-type"
 #~ msgid "Q3D Object file"
 #~ msgstr "Q3D Objektdatei"
index e7acd7e151f21d0be149d3e9b5a4c21143a9cf00..1d00755eb3fcd9fd108d368081b51cdd84a34042 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
 "PO-Revision-Date: 2017-01-05 10:30+0000\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
@@ -27,27 +27,27 @@ msgstr ""
 "\n"
 "Activate one with Sketch -> In Workplane."
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr "Clipboard is empty; nothing to paste."
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr "Number of copies to paste must be at least one."
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr "Scale cannot be zero."
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr "Select one point to define origin of rotation."
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr "Select two points to define translation vector."
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
@@ -55,23 +55,23 @@ msgstr ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr "Too many items to paste; split this into smaller pastes."
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr "No workplane active."
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr "Bad format: specify coordinates as x, y, z"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr "Bad format: specify color as r, g, b"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
@@ -79,24 +79,24 @@ msgstr ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr "Specify between 0 and %d digits after the decimal."
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr "Export scale must not be zero!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr "Cutter radius offset must not be negative!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr "Bad value: autosave interval should be positive"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr "Bad format: specify interval in integral minutes"
 
@@ -167,115 +167,135 @@ msgstr "length-ratio"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr "arc-arc-length-ratio"
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr "arc-line-length-ratio"
+
+#: constraint.cpp:27
+msgctxt "constr-name"
 msgid "length-difference"
 msgstr "length-difference"
 
-#: constraint.cpp:26
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr "arc-arc-len-difference"
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr "arc-line-len-difference"
+
+#: constraint.cpp:30
 msgctxt "constr-name"
 msgid "symmetric"
 msgstr "symmetric"
 
-#: constraint.cpp:27
+#: constraint.cpp:31
 msgctxt "constr-name"
 msgid "symmetric-h"
 msgstr "symmetric-h"
 
-#: constraint.cpp:28
+#: constraint.cpp:32
 msgctxt "constr-name"
 msgid "symmetric-v"
 msgstr "symmetric-v"
 
-#: constraint.cpp:29
+#: constraint.cpp:33
 msgctxt "constr-name"
 msgid "symmetric-line"
 msgstr "symmetric-line"
 
-#: constraint.cpp:30
+#: constraint.cpp:34
 msgctxt "constr-name"
 msgid "at-midpoint"
 msgstr "at-midpoint"
 
-#: constraint.cpp:31
+#: constraint.cpp:35
 msgctxt "constr-name"
 msgid "horizontal"
 msgstr "horizontal"
 
-#: constraint.cpp:32
+#: constraint.cpp:36
 msgctxt "constr-name"
 msgid "vertical"
 msgstr "vertical"
 
-#: constraint.cpp:33
+#: constraint.cpp:37
 msgctxt "constr-name"
 msgid "diameter"
 msgstr "diameter"
 
-#: constraint.cpp:34
+#: constraint.cpp:38
 msgctxt "constr-name"
 msgid "pt-on-circle"
 msgstr "pt-on-circle"
 
-#: constraint.cpp:35
+#: constraint.cpp:39
 msgctxt "constr-name"
 msgid "same-orientation"
 msgstr "same-orientation"
 
-#: constraint.cpp:36
+#: constraint.cpp:40
 msgctxt "constr-name"
 msgid "angle"
 msgstr "angle"
 
-#: constraint.cpp:37
+#: constraint.cpp:41
 msgctxt "constr-name"
 msgid "parallel"
 msgstr "parallel"
 
-#: constraint.cpp:38
+#: constraint.cpp:42
 msgctxt "constr-name"
 msgid "arc-line-tangent"
 msgstr "arc-line-tangent"
 
-#: constraint.cpp:39
+#: constraint.cpp:43
 msgctxt "constr-name"
 msgid "cubic-line-tangent"
 msgstr "cubic-line-tangent"
 
-#: constraint.cpp:40
+#: constraint.cpp:44
 msgctxt "constr-name"
 msgid "curve-curve-tangent"
 msgstr "curve-curve-tangent"
 
-#: constraint.cpp:41
+#: constraint.cpp:45
 msgctxt "constr-name"
 msgid "perpendicular"
 msgstr "perpendicular"
 
-#: constraint.cpp:42
+#: constraint.cpp:46
 msgctxt "constr-name"
 msgid "eq-radius"
 msgstr "eq-radius"
 
-#: constraint.cpp:43
+#: constraint.cpp:47
 msgctxt "constr-name"
 msgid "eq-angle"
 msgstr "eq-angle"
 
-#: constraint.cpp:44
+#: constraint.cpp:48
 msgctxt "constr-name"
 msgid "eq-line-len-arc-len"
 msgstr "eq-line-len-arc-len"
 
-#: constraint.cpp:45
+#: constraint.cpp:49
 msgctxt "constr-name"
 msgid "lock-where-dragged"
 msgstr "lock-where-dragged"
 
-#: constraint.cpp:46
+#: constraint.cpp:50
 msgctxt "constr-name"
 msgid "comment"
 msgstr "comment"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
@@ -283,7 +303,7 @@ msgstr ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
@@ -291,7 +311,7 @@ msgstr ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
@@ -299,7 +319,7 @@ msgstr ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -323,7 +343,7 @@ msgstr ""
 "    * a plane face and a point (minimum distance)\n"
 "    * a circle or an arc (diameter)\n"
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -343,7 +363,7 @@ msgstr ""
 "    * a point and a circle or arc (point on curve)\n"
 "    * a point and a plane face (point on face)\n"
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -371,29 +391,37 @@ msgstr ""
 "    * two circles or arcs (equal radius)\n"
 "    * a line segment and an arc (line segment length equals arc length)\n"
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -405,7 +433,7 @@ msgstr ""
 "    * a line segment and a point (point at midpoint)\n"
 "    * a line segment and a workplane (line's midpoint on plane)\n"
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -425,7 +453,7 @@ msgstr ""
 "    * workplane, and two points or a line segment (symmetric about "
 "workplane)\n"
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
@@ -433,7 +461,7 @@ msgstr ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
@@ -441,7 +469,7 @@ msgstr ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -455,7 +483,7 @@ msgstr ""
 "    * two points\n"
 "    * a line segment\n"
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
@@ -467,15 +495,15 @@ msgstr ""
 "\n"
 "    * two normals\n"
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr "Must select an angle constraint."
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr "Must select a constraint with associated label."
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -489,11 +517,11 @@ msgstr ""
 "    * a line segment and a normal\n"
 "    * two normals\n"
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr "Curve-curve tangency must apply in workplane."
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -511,7 +539,7 @@ msgstr ""
 "    * two normals (parallel)\n"
 "    * two line segments, arcs, or beziers, that share an endpoint (tangent)\n"
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -525,7 +553,7 @@ msgstr ""
 "    * a line segment and a normal\n"
 "    * two normals\n"
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
@@ -537,7 +565,11 @@ msgstr ""
 "\n"
 "    * a point\n"
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr "click center of comment text"
 
@@ -565,25 +597,25 @@ msgstr ""
 "    * a point and two line segments (plane through point and parallel to "
 "lines)\n"
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
 msgstr "Active group mesh is empty; nothing to export."
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr "freehand lines were replaced with continuous lines"
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr "zigzag lines were replaced with continuous lines"
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
@@ -599,7 +631,11 @@ msgctxt "group-name"
 msgid "#references"
 msgstr "#references"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "The file is empty. It may be corrupt."
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
@@ -607,18 +643,18 @@ msgstr ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr "Missing File"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
 msgstr "The linked file “%s” is not present."
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -631,17 +667,17 @@ msgstr ""
 "If you decline, any geometry that depends on the missing file will be "
 "permanently removed."
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr "&Yes"
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr "&No"
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr "&Cancel"
@@ -815,295 +851,307 @@ msgid "Use &Perspective Projection"
 msgstr "Use &Perspective Projection"
 
 #: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr "Show E&xploded View"
+
+#: graphicswin.cpp:98
 msgid "Dimension &Units"
 msgstr "Dimension &Units"
 
-#: graphicswin.cpp:98
+#: graphicswin.cpp:99
 msgid "Dimensions in &Millimeters"
 msgstr "Dimensions in &Millimeters"
 
-#: graphicswin.cpp:99
+#: graphicswin.cpp:100
 msgid "Dimensions in M&eters"
 msgstr "Dimensions in M&eters"
 
-#: graphicswin.cpp:100
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr "Dimensions in &Inches"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr "Dimensions in &Feet and Inches"
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "Show &Toolbar"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "Show Property Bro&wser"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "&Full Screen"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "&New Group"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr "Sketch In &3d"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr "Sketch In New &Workplane"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "Step &Translating"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "Step &Rotating"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "E&xtrude"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
 msgstr "&Helix"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "&Lathe"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
 msgstr "Re&volve"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
 msgstr "Link / Assemble..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr "Link Recent"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "&Sketch"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr "In &Workplane"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr "Anywhere In &3d"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "Datum &Point"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "&Workplane"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "Line &Segment"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "C&onstruction Line Segment"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "&Rectangle"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "&Circle"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "&Arc of a Circle"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "&Bezier Cubic Spline"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr "&Text in TrueType Font"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr "&Image"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "To&ggle Construction"
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "Tangent &Arc at Point"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "Split Curves at &Intersection"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "&Constrain"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "&Distance / Diameter"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "Re&ference Dimension"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "A&ngle"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "Reference An&gle"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "Other S&upplementary Angle"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "Toggle R&eference Dim"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "&Horizontal"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "&Vertical"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "&On Point / Curve / Plane"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "E&qual Length / Radius / Angle"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "Length Ra&tio"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr "Length / Arc Ra&tio"
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "Length Diff&erence"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr "Length / Arc Diff&erence"
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "At &Midpoint"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "S&ymmetric"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "Para&llel / Tangent"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "&Perpendicular"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "Same Orient&ation"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "Lock Point Where &Dragged"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "Comment"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "&Analyze"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "Measure &Volume"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "Measure A&rea"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "Measure &Perimeter"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "Show &Interfering Parts"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "Show &Naked Edges"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
 msgstr "Show &Center of Mass"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
 msgstr "Show &Underconstrained Points"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "&Trace Point"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr "&Stop Tracing..."
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "Step &Dimension..."
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "&Help"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "&Language"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "&Website / Manual"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr "&Go to GitHub commit"
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "&About"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr "(no recent files)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
 msgstr "File '%s' does not exist."
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr "No workplane is active, so the grid will not appear."
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -1117,17 +1165,17 @@ msgstr ""
 "For a perspective projection, modify the perspective factor in the "
 "configuration screen. A value around 0.3 is typical."
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr ""
 "Select a point; this point will become the center of the view on screen."
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr "No additional entities share endpoints with the selected entities."
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
@@ -1135,7 +1183,7 @@ msgstr ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
@@ -1143,7 +1191,7 @@ msgstr ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
@@ -1151,11 +1199,11 @@ msgstr ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr "No workplane selected. Activating default workplane for this group."
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
@@ -1165,7 +1213,7 @@ msgstr ""
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
 "workplane group."
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
@@ -1173,47 +1221,47 @@ msgstr ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr "click point on arc (draws anti-clockwise)"
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr "click to place datum point"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr "click first point of line segment"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr "click first point of construction line segment"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr "click first point of cubic segment"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr "click center of circle"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr "click origin of workplane"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr "click one corner of rectangle"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr "click top left of text"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr "click top left of image"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1226,13 +1274,14 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr "sketch-in-3d"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
@@ -1240,9 +1289,10 @@ msgstr ""
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
@@ -1250,16 +1300,16 @@ msgstr ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr "extrude"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr "Lathe operation can only be applied to planar sketches."
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1273,16 +1323,16 @@ msgstr ""
 "to line / normal, through point)\n"
 "    * a line segment (revolved about line segment)\n"
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr "lathe"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr "Revolve operation can only be applied to planar sketches."
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1296,16 +1346,16 @@ msgstr ""
 "to line / normal, through point)\n"
 "    * a line segment (revolved about line segment)\n"
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
 msgstr "revolve"
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr "Helix operation can only be applied to planar sketches."
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1319,12 +1369,12 @@ msgstr ""
 "to line / normal, through point)\n"
 "    * a line segment (revolved about line segment)\n"
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
 msgstr "helix"
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1340,41 +1390,45 @@ msgstr ""
 "    * a point and a line or a normal (rotate about an axis through the "
 "point, and parallel to line / normal)\n"
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr "rotate"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr "translate"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr "(unnamed)"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
 msgstr "not closed contour, or not all same style!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr "points not all coplanar!"
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr "contour is self-intersecting!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr "zero-length edge!"
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr "Text-formated STL files are not currently supported"
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr "Must be sketching in workplane to create tangent arc."
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
@@ -1382,7 +1436,7 @@ msgstr ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
@@ -1390,15 +1444,15 @@ msgstr ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr "Couldn't split this entity; lines, circles, or cubics only."
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr "Must be sketching in workplane to split."
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
@@ -1406,107 +1460,107 @@ msgstr ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr "Can't split; no intersection found."
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "Assign to Style"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "No Style"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "Newly Created Custom Style..."
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "Group Info"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "Style Info"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "Select Edge Chain"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "Toggle Reference Dimension"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "Other Supplementary Angle"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "Snap to Grid"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "Remove Spline Point"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "Add Spline Point"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr "Cannot add spline point: maximum number of points reached."
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "Toggle Construction"
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "Delete Point-Coincident Constraint"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "Cut"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "Copy"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "Select All"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "Paste"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "Paste Transformed..."
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "Delete"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "Unselect All"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "Unselect Hovered"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "Zoom to Fit"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr "click next point of line, or press Esc"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1514,15 +1568,15 @@ msgstr ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr "click to place other corner of rectangle"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr "click to set radius"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1530,21 +1584,21 @@ msgstr ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr "click to place point"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr "click next point of cubic, or press Esc"
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1552,11 +1606,11 @@ msgstr ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
 msgstr "click to place bottom right of text"
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1564,193 +1618,199 @@ msgstr ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
 msgstr "SolveSpace models"
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr "ALL"
+
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
 msgstr "IDF circuit board"
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr "STL triangle mesh"
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr "PNG image"
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr "STL mesh"
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr "Wavefront OBJ mesh"
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
 msgstr "Three.js-compatible mesh, with viewer"
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr "Three.js-compatible mesh, mesh only"
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
 msgstr "VRML text file"
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr "STEP file"
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr "PDF file"
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr "Encapsulated PostScript"
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr "Scalable Vector Graphics"
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr "DXF file (AutoCAD 2007)"
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr "HPGL file"
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr "G Code"
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr "AutoCAD DXF and DWG files"
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr "Comma-separated values"
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr "untitled"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr "Save File"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr "Open File"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr "_Cancel"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr "_Save"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
 msgstr "_Open"
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr "Autosave Available"
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
 msgstr "An autosave file is available for this sketch."
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
 msgstr "Do you want to load the autosave file instead?"
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
 msgstr "&Load autosave"
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
 msgstr "Do&n't Load"
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr "Modified File"
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
 msgstr "Do you want to save the changes you made to the sketch “%s”?"
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
 msgstr "Do you want to save the changes you made to the new sketch?"
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
 msgstr "Your changes will be lost if you don't save them."
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
 msgstr "&Save"
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
 msgstr "Do&n't Save"
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr "(new sketch)"
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr "Property Browser"
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
@@ -1760,7 +1820,7 @@ msgstr ""
 "is probably not what you want; hide them by clicking the link at the top of "
 "the text window."
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
@@ -1769,19 +1829,19 @@ msgstr ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
 "dwg."
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
 msgstr "Constraint must have a label, and must not be a reference dimension."
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr "Bad selection for step dimension; select a constraint."
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr "The assembly does not interfere, good."
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
@@ -1792,7 +1852,7 @@ msgstr ""
 "\n"
 "    %s"
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1805,7 +1865,7 @@ msgstr ""
 "\n"
 "    %s"
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1817,7 +1877,7 @@ msgstr ""
 "Curved surfaces have been approximated as triangles.\n"
 "This introduces error, typically of around 1%."
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1834,7 +1894,7 @@ msgstr ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
@@ -1842,7 +1902,7 @@ msgstr ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1859,7 +1919,7 @@ msgstr ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1876,36 +1936,36 @@ msgstr ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr "Bad selection for perimeter; select line segments, arcs, and curves."
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
 msgstr "Bad selection for trace; select a single point."
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
 msgstr "Couldn't write to '%s'"
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
 msgstr "The mesh is self-intersecting (NOT okay, invalid)."
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
 msgstr "The mesh is not self-intersecting (okay, valid)."
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
 msgstr "The mesh has naked edges (NOT okay, invalid)."
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
 msgstr "The mesh is watertight (okay, valid)."
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1916,7 +1976,7 @@ msgstr ""
 "\n"
 "The model contains %d triangles, from %d surfaces."
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1931,7 +1991,7 @@ msgstr ""
 "\n"
 "Zero problematic edges, good.%s"
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1946,7 +2006,7 @@ msgstr ""
 "\n"
 "%d problematic edges, bad.%s"
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1975,7 +2035,7 @@ msgstr ""
 "\n"
 "© 2008-%d Jonathan Westhues and other authors.\n"
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
@@ -1983,27 +2043,27 @@ msgstr ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
 msgstr "Style name cannot be empty"
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr "Can't repeat fewer than 1 time."
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr "Can't repeat more than 999 times."
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
 msgstr "Group name cannot be empty"
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr "Opacity must be between zero and one."
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr "Radius cannot be zero or negative."
 
@@ -2158,14 +2218,64 @@ msgctxt "button"
 msgid "&OK"
 msgstr "&OK"
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr "Scale cannot be zero or negative."
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr "Bad format: specify x, y, z"
 
+#~ msgid "&Mirror"
+#~ msgstr "&Mirror"
+
+#~ msgctxt "group-name"
+#~ msgid "mirror"
+#~ msgstr "mirror"
+
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "Length Ra&tio"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "Length Diff&erence"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+
 #~ msgctxt "file-type"
 #~ msgid "Q3D Object file"
 #~ msgstr "Q3D Object file"
diff --git a/res/locales/es_AR.po b/res/locales/es_AR.po
new file mode 100644 (file)
index 0000000..ac9052f
--- /dev/null
@@ -0,0 +1,2284 @@
+# Spanish/Argentina translations for SolveSpace package.
+# Copyright (C) 2017 the SolveSpace authors
+# This file is distributed under the same license as the SolveSpace package.
+# Maxi <andesfreedesign@gmail.com>, 2021.
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: SolveSpace 3.0\n"
+"Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2021-09-17 \n"
+"Last-Translator: andesfreedesign@gmail.com\n"
+"Language-Team: AndesFreeDesign\n"
+"Language: es_AR\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"
+
+#: clipboard.cpp:309
+msgid ""
+"Cut, paste, and copy work only in a workplane.\n"
+"\n"
+"Activate one with Sketch -> In Workplane."
+msgstr ""
+"Cortar, pegar y copiar trabajo\n"
+"solo en un plano de trabajo.\n"
+"Activar uno con Croquis-> En Plano de trabajo"
+
+#: clipboard.cpp:326
+msgid "Clipboard is empty; nothing to paste."
+msgstr "El portapapeles está vacío; nada que pegar."
+
+#: clipboard.cpp:373
+msgid "Number of copies to paste must be at least one."
+msgstr "El número de copias para pegar debe ser al menos una."
+
+#: clipboard.cpp:389 textscreens.cpp:833
+msgid "Scale cannot be zero."
+msgstr "La escala no puede ser cero."
+
+#: clipboard.cpp:431
+msgid "Select one point to define origin of rotation."
+msgstr "Seleccione un punto para definir el origen de la rotación."
+
+#: clipboard.cpp:443
+msgid "Select two points to define translation vector."
+msgstr "Seleccione dos puntos para definir el vector de traslación."
+
+#: clipboard.cpp:453
+msgid ""
+"Transformation is identity. So all copies will be exactly on top of each "
+"other."
+msgstr ""
+"No se especificó ninguna transformación. Todas las copias estarán ubicadas "
+"en el mismo lugar."
+
+#: clipboard.cpp:457
+msgid "Too many items to paste; split this into smaller pastes."
+msgstr "Demasiados elementos para pegar; divida esto en partes más pequeñas."
+
+#: clipboard.cpp:462
+msgid "No workplane active."
+msgstr "Ningún plano de trabajo activo."
+
+#: confscreen.cpp:381
+msgid "Bad format: specify coordinates as x, y, z"
+msgstr "Formato incorrecto: especifique las coordenadas como x, y, z"
+
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
+msgid "Bad format: specify color as r, g, b"
+msgstr "Formato incorrecto: especifique color como r, g, b"
+
+#: confscreen.cpp:417
+msgid ""
+"The perspective factor will have no effect until you enable View -> Use "
+"Perspective Projection."
+msgstr ""
+"El factor de perspectiva no tendrá ningún efecto hasta que habilite Ver -> "
+"UsarProyección Perspectiva."
+
+#: confscreen.cpp:435 confscreen.cpp:445
+#, c-format
+msgid "Specify between 0 and %d digits after the decimal."
+msgstr "Especifique entre 0 y %d dígitos después del decimal."
+
+#: confscreen.cpp:457
+msgid "Export scale must not be zero!"
+msgstr "¡La escala de exportación no debe ser cero!"
+
+#: confscreen.cpp:469
+msgid "Cutter radius offset must not be negative!"
+msgstr "¡El desfase del radio de corte no debe ser negativo!"
+
+#: confscreen.cpp:528
+msgid "Bad value: autosave interval should be positive"
+msgstr "Valor incorrecto: el intervalo de autoguardado debe ser positivo"
+
+#: confscreen.cpp:531
+msgid "Bad format: specify interval in integral minutes"
+msgstr "Formato incorrecto: especifique el intervalo en minutos integrales"
+
+#: constraint.cpp:12
+msgctxt "constr-name"
+msgid "pts-coincident"
+msgstr "ps-coincidente"
+
+#: constraint.cpp:13
+msgctxt "constr-name"
+msgid "pt-pt-distance"
+msgstr "p-p-distancia"
+
+#: constraint.cpp:14
+msgctxt "constr-name"
+msgid "pt-line-distance"
+msgstr "p-línea-distancia"
+
+#: constraint.cpp:15
+msgctxt "constr-name"
+msgid "pt-plane-distance"
+msgstr "p-plano-distancia"
+
+#: constraint.cpp:16
+msgctxt "constr-name"
+msgid "pt-face-distance"
+msgstr "p-cara-distancia"
+
+#: constraint.cpp:17
+msgctxt "constr-name"
+msgid "proj-pt-pt-distance"
+msgstr "proy-p-p-distancia"
+
+#: constraint.cpp:18
+msgctxt "constr-name"
+msgid "pt-in-plane"
+msgstr "p-en-plano"
+
+#: constraint.cpp:19
+msgctxt "constr-name"
+msgid "pt-on-line"
+msgstr "p-sobre-línea"
+
+#: constraint.cpp:20
+msgctxt "constr-name"
+msgid "pt-on-face"
+msgstr "p-sobre-cara"
+
+#: constraint.cpp:21
+msgctxt "constr-name"
+msgid "eq-length"
+msgstr "igual-longitud"
+
+#: constraint.cpp:22
+msgctxt "constr-name"
+msgid "eq-length-and-pt-ln-dist"
+msgstr "igual-longitud-y-p-línea-dist"
+
+#: constraint.cpp:23
+msgctxt "constr-name"
+msgid "eq-pt-line-distances"
+msgstr "igual-p-línea-distancias"
+
+#: constraint.cpp:24
+msgctxt "constr-name"
+msgid "length-ratio"
+msgstr "longitud-radio"
+
+#: constraint.cpp:25
+msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr ""
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr ""
+
+#: constraint.cpp:27
+msgctxt "constr-name"
+msgid "length-difference"
+msgstr "longitud-diferencia"
+
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr ""
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr ""
+
+#: constraint.cpp:30
+msgctxt "constr-name"
+msgid "symmetric"
+msgstr "simetría"
+
+#: constraint.cpp:31
+msgctxt "constr-name"
+msgid "symmetric-h"
+msgstr "simetría-h"
+
+#: constraint.cpp:32
+msgctxt "constr-name"
+msgid "symmetric-v"
+msgstr "simetría-v"
+
+#: constraint.cpp:33
+msgctxt "constr-name"
+msgid "symmetric-line"
+msgstr "simetría-línea"
+
+#: constraint.cpp:34
+msgctxt "constr-name"
+msgid "at-midpoint"
+msgstr "en-puntoMedio"
+
+#: constraint.cpp:35
+msgctxt "constr-name"
+msgid "horizontal"
+msgstr "horizontal"
+
+#: constraint.cpp:36
+msgctxt "constr-name"
+msgid "vertical"
+msgstr "vertical"
+
+#: constraint.cpp:37
+msgctxt "constr-name"
+msgid "diameter"
+msgstr "diámetro"
+
+#: constraint.cpp:38
+msgctxt "constr-name"
+msgid "pt-on-circle"
+msgstr "p-sobre-círculo"
+
+#: constraint.cpp:39
+msgctxt "constr-name"
+msgid "same-orientation"
+msgstr "misma-orientación"
+
+#: constraint.cpp:40
+msgctxt "constr-name"
+msgid "angle"
+msgstr "ángulo"
+
+#: constraint.cpp:41
+msgctxt "constr-name"
+msgid "parallel"
+msgstr "paralela"
+
+#: constraint.cpp:42
+msgctxt "constr-name"
+msgid "arc-line-tangent"
+msgstr "arco-línea-tangente"
+
+#: constraint.cpp:43
+msgctxt "constr-name"
+msgid "cubic-line-tangent"
+msgstr "cúbica-línea-tangente"
+
+#: constraint.cpp:44
+msgctxt "constr-name"
+msgid "curve-curve-tangent"
+msgstr "curva-curva-tangente"
+
+#: constraint.cpp:45
+msgctxt "constr-name"
+msgid "perpendicular"
+msgstr "perpendicular"
+
+#: constraint.cpp:46
+msgctxt "constr-name"
+msgid "eq-radius"
+msgstr "igual-radio"
+
+#: constraint.cpp:47
+msgctxt "constr-name"
+msgid "eq-angle"
+msgstr "igual-ángulo"
+
+#: constraint.cpp:48
+msgctxt "constr-name"
+msgid "eq-line-len-arc-len"
+msgstr "igual-línea-long-arco-long"
+
+#: constraint.cpp:49
+msgctxt "constr-name"
+msgid "lock-where-dragged"
+msgstr "fijación"
+
+#: constraint.cpp:50
+msgctxt "constr-name"
+msgid "comment"
+msgstr "comentario"
+
+#: constraint.cpp:144
+msgid ""
+"The tangent arc and line segment must share an endpoint. Constrain them with "
+"Constrain -> On Point before constraining tangent."
+msgstr ""
+"El arco tangente y la línea deben compartir un punto final. Restringirlos "
+"con Restringir -> En el punto antes de restringir la tangente."
+
+#: constraint.cpp:163
+msgid ""
+"The tangent cubic and line segment must share an endpoint. Constrain them "
+"with Constrain -> On Point before constraining tangent."
+msgstr ""
+"La tangente cúbica y la línea deben compartir un punto final. Restringirlos "
+"con Restringir -> En el punto antes de restringir la tangente."
+
+#: constraint.cpp:189
+msgid ""
+"The curves must share an endpoint. Constrain them with Constrain -> On Point "
+"before constraining tangent."
+msgstr ""
+"Las curvas deben compartir un punto final. Restringirlos con Restringir -> "
+"En el punto antes de restringir la tangente."
+
+#: constraint.cpp:238
+msgid ""
+"Bad selection for distance / diameter constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two points (distance between points)\n"
+"    * a line segment (length)\n"
+"    * two points and a line segment or normal (projected distance)\n"
+"    * a workplane and a point (minimum distance)\n"
+"    * a line segment and a point (minimum distance)\n"
+"    * a plane face and a point (minimum distance)\n"
+"    * a circle or an arc (diameter)\n"
+msgstr ""
+"Mala selección para la restricción de distancia / diámetro. Esta restricción "
+"puede aplicarse a:\n"
+"\n"
+"    * dos puntos (distancia entre puntos) \n"
+"    * un segmento de línea (longitud) \n"
+"    * dos puntos y un segmento de línea o normal (distancia proyectada) \n"
+"    * un plano de trabajo y un punto (distancia mínima) \n"
+"    * un segmento de línea y un punto (distancia mínima) \n"
+"    * una cara plana y un punto (distancia mínima) \n"
+"    * un círculo o un arco (diámetro) \n"
+
+#: constraint.cpp:291
+msgid ""
+"Bad selection for on point / curve / plane constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two points (points coincident)\n"
+"    * a point and a workplane (point in plane)\n"
+"    * a point and a line segment (point on line)\n"
+"    * a point and a circle or arc (point on curve)\n"
+"    * a point and a plane face (point on face)\n"
+msgstr ""
+"Mala selección para una restricción de punto / curva / plano. Esta "
+"restricción puedeaplicar a: \n"
+"\n"
+"    * dos puntos (puntos coincidentes) \n"
+"    * un punto y un plano de trabajo (punto en el plano) \n"
+"    * un punto y un segmento de línea (punto en la línea) \n"
+"    * un punto y un círculo o arco (punto en la curva) \n"
+"    * un punto y una cara plana (punto en la cara) \n"
+
+#: constraint.cpp:353
+msgid ""
+"Bad selection for equal length / radius constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two line segments (equal length)\n"
+"    * two line segments and two points (equal point-line distances)\n"
+"    * a line segment and two points (equal point-line distances)\n"
+"    * a line segment, and a point and line segment (point-line distance "
+"equals length)\n"
+"    * four line segments or normals (equal angle between A,B and C,D)\n"
+"    * three line segments or normals (equal angle between A,B and B,C)\n"
+"    * two circles or arcs (equal radius)\n"
+"    * a line segment and an arc (line segment length equals arc length)\n"
+msgstr ""
+"Mala selección para restricción de igualdad longitud / radio. Esta "
+"restricción puede aplicar a:\n"
+"\n"
+"    * dos segmentos de línea (igual longitud)\n"
+"    * dos segmentos de línea y dos puntos (distancias de línea-punto "
+"iguales)\n"
+"    * un segmento de línea y dos puntos (distancias punto-línea iguales)\n"
+"    * un segmento de línea, y un punto y un segmento de línea (distancia "
+"punto-línea igual a la longitud)\n"
+"    * cuatro segmentos de línea o normales (ángulo igual entre A,B y C,D)\n"
+"    * tres segmentos de línea o normales (ángulo igual entre A,B y B,C)\n"
+"    * 2 círculos o arcos (igual radio)\n"
+"    * un segmento de línea y un arco (la longitud del segmento de línea es "
+"igual a la longitud del arco)\n"
+
+#: constraint.cpp:407
+msgid ""
+"Bad selection for length ratio constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
+msgstr ""
+
+#: constraint.cpp:441
+msgid ""
+"Bad selection for length difference constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
+msgstr ""
+
+#: constraint.cpp:472
+msgid ""
+"Bad selection for at midpoint constraint. This constraint can apply to:\n"
+"\n"
+"    * a line segment and a point (point at midpoint)\n"
+"    * a line segment and a workplane (line's midpoint on plane)\n"
+msgstr ""
+"Mala selección para una restricción de punto medio. Esta restricción se "
+"puede aplicar a:\n"
+"\n"
+"    * un segmento de línea y un punto (punto en el punto medio)\n"
+"    * un segmento de línea y un plano de trabajo (punto medio de la línea en "
+"el plano)\n"
+
+#: constraint.cpp:530
+msgid ""
+"Bad selection for symmetric constraint. This constraint can apply to:\n"
+"\n"
+"    * two points or a line segment (symmetric about workplane's coordinate "
+"axis)\n"
+"    * line segment, and two points or a line segment (symmetric about line "
+"segment)\n"
+"    * workplane, and two points or a line segment (symmetric about "
+"workplane)\n"
+msgstr ""
+"Mala selección por restricción simétrica. Esta restricción se puede aplicar "
+"a:\n"
+"\n"
+"    * dos puntos o un segmento de línea (simétrico con respecto al eje de "
+"coordenadas del plano de trabajo)\n"
+"    * segmento de línea, y dos puntos o un segmento de línea (simétrico con "
+"respecto al segmento de línea)\n"
+"    * plano de trabajo, y dos puntos o un segmento de recta (simétrico sobre "
+"plano de trabajo)\n"
+
+#: constraint.cpp:545
+msgid ""
+"A workplane must be active when constraining symmetric without an explicit "
+"symmetry plane."
+msgstr ""
+"Un plano de trabajo debe estar activo al restringir simétrico sin un plano "
+"de simetría explícito."
+
+#: constraint.cpp:579
+msgid ""
+"Activate a workplane (with Sketch -> In Workplane) before applying a "
+"horizontal or vertical constraint."
+msgstr ""
+"Active un plano de trabajo (con Croquis -> En plano de trabajo) antes de "
+"aplicar una restricción horizontal o vertical."
+
+#: constraint.cpp:592
+msgid ""
+"Bad selection for horizontal / vertical constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two points\n"
+"    * a line segment\n"
+msgstr ""
+"Mala selección por restricción horizontal / vertical. Esta restricción puede "
+"aplicar a:\n"
+"\n"
+"    * dos puntos\n"
+"    * un segmento de línea\n"
+
+#: constraint.cpp:613
+msgid ""
+"Bad selection for same orientation constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two normals\n"
+msgstr ""
+"Mala selección para la misma restricción de orientación. Esta restricción "
+"puede aplicarse a:\n"
+"\n"
+"    * dos normales\n"
+
+#: constraint.cpp:663
+msgid "Must select an angle constraint."
+msgstr "Debe seleccionar una restricción de ángulo."
+
+#: constraint.cpp:676
+msgid "Must select a constraint with associated label."
+msgstr "Debe seleccionar una restricción con etiqueta asociada."
+
+#: constraint.cpp:687
+msgid ""
+"Bad selection for angle constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * a line segment and a normal\n"
+"    * two normals\n"
+msgstr ""
+"Mala selección por restricción de ángulo. Esta restricción se puede aplicar "
+"a:\n"
+"\n"
+"    * dos segmentos de línea\n"
+"    * un segmento de linea y una normal\n"
+"    * dos normales\n"
+
+#: constraint.cpp:754
+msgid "Curve-curve tangency must apply in workplane."
+msgstr "La tangencia curva-curva debe aplicarse en el plano de trabajo."
+
+#: constraint.cpp:766
+msgid ""
+"Bad selection for parallel / tangent constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two line segments (parallel)\n"
+"    * a line segment and a normal (parallel)\n"
+"    * two normals (parallel)\n"
+"    * two line segments, arcs, or beziers, that share an endpoint (tangent)\n"
+msgstr ""
+"Mala selección para restricción de paralelo / tangente. Esta restricción "
+"puede aplicarse a:\n"
+"\n"
+"    * dos segmentos de línea (paralelos)\n"
+"    * un segmento de línea y una normal (paralelas)\n"
+"    * dos normales (paralelas)\n"
+"    * dos segmentos de línea, arcos, o beziers, que comparten un punto final "
+"(tangente)\n"
+
+#: constraint.cpp:784
+msgid ""
+"Bad selection for perpendicular constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * a line segment and a normal\n"
+"    * two normals\n"
+msgstr ""
+"Mala selección por restricción perpendicular. Esta restricción se puede "
+"aplicar a:\n"
+"\n"
+"    * dos segmentos de línea\n"
+"    * un segmento de línea y una normal\n"
+"    * dos normales\n"
+
+#: constraint.cpp:799
+msgid ""
+"Bad selection for lock point where dragged constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * a point\n"
+msgstr ""
+"Mala selección para el punto de bloqueo donde se arrastró la restricción. "
+"Esta restricción puede aplicar a:\n"
+"\n"
+"    * un punto\n"
+
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "NUEVO COMENTARIO -- DOBLE-CLIC PARA EDITAR"
+
+#: constraint.cpp:818
+msgid "click center of comment text"
+msgstr "clic en el centro del texto del comentario"
+
+#: export.cpp:19
+msgid ""
+"No solid model present; draw one with extrudes and revolves, or use Export "
+"2d View to export bare lines and curves."
+msgstr ""
+"No hay un modelo sólido presente; dibuje uno con extrusiones y revoluciones, "
+"o use Exportar Vista 2d para exportar líneas y curvas desnudas."
+
+#: export.cpp:61
+msgid ""
+"Bad selection for export section. Please select:\n"
+"\n"
+"    * nothing, with an active workplane (workplane is section plane)\n"
+"    * a face (section plane through face)\n"
+"    * a point and two line segments (plane through point and parallel to "
+"lines)\n"
+msgstr ""
+"Mala selección para la sección de exportación. Por favor seleccione:\n"
+"\n"
+"    * nada, con un plano de trabajo activo (el plano de trabajo es un plano "
+"de sección)\n"
+"    * una cara (plano de sección a través de la cara)\n"
+"    * un punto y dos segmentos de línea (plano que pasa por el punto y "
+"paralelo a las líneas)\n"
+
+#: export.cpp:818
+msgid "Active group mesh is empty; nothing to export."
+msgstr "La malla del grupo activo está vacía; nada para exportar."
+
+#: exportvector.cpp:336
+msgid "freehand lines were replaced with continuous lines"
+msgstr "Las líneas a mano alzada fueron reemplazadas por líneas continuas."
+
+#: exportvector.cpp:338
+msgid "zigzag lines were replaced with continuous lines"
+msgstr "Las líneas en zigzag fueron reemplazadas por líneas continuas."
+
+#: exportvector.cpp:592
+msgid ""
+"Some aspects of the drawing have no DXF equivalent and were not exported:\n"
+msgstr ""
+"Algunos aspectos del dibujo no tienen equivalente DXF y no se exportaron:\n"
+
+#: exportvector.cpp:838
+msgid ""
+"PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
+msgstr ""
+"El tamaño de la página PDF supera las 5080mm x 5080mm; muchos usuarios "
+"pueden rechazar este archivo."
+
+#: file.cpp:44 group.cpp:91
+msgctxt "group-name"
+msgid "sketch-in-plane"
+msgstr "croquis-en-plano"
+
+#: file.cpp:62
+msgctxt "group-name"
+msgid "#references"
+msgstr "#referencias"
+
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "El archivo esta vacío. Puede estar corrupto."
+
+#: file.cpp:555
+msgid ""
+"Unrecognized data in file. This file may be corrupt, or from a newer version "
+"of the program."
+msgstr ""
+"Datos no reconocidos en el archivo. Este archivo puede estar dañado o ser de "
+"una versión más reciente  del programa."
+
+#: file.cpp:867
+msgctxt "title"
+msgid "Missing File"
+msgstr "Archivo perdido"
+
+#: file.cpp:868
+#, c-format
+msgctxt "dialog"
+msgid "The linked file “%s” is not present."
+msgstr "El archivo vinculado “%s” no esta presente."
+
+#: file.cpp:870
+msgctxt "dialog"
+msgid ""
+"Do you want to locate it manually?\n"
+"\n"
+"If you decline, any geometry that depends on the missing file will be "
+"permanently removed."
+msgstr ""
+"¿Quieres localizarlo manualmente?\n"
+"\n"
+"Si lo rechaza, cualquier geometría que dependa del archivo faltante se "
+"eliminará permanentemente."
+
+#: file.cpp:873
+msgctxt "button"
+msgid "&Yes"
+msgstr "&Si"
+
+#: file.cpp:875
+msgctxt "button"
+msgid "&No"
+msgstr "&No"
+
+#: file.cpp:877 solvespace.cpp:611
+msgctxt "button"
+msgid "&Cancel"
+msgstr "&Cancelar"
+
+#: graphicswin.cpp:41
+msgid "&File"
+msgstr "&Archivo"
+
+#: graphicswin.cpp:42
+msgid "&New"
+msgstr "&Nuevo"
+
+#: graphicswin.cpp:43
+msgid "&Open..."
+msgstr "&Abrir..."
+
+#: graphicswin.cpp:44
+msgid "Open &Recent"
+msgstr "Abrir &Reciente"
+
+#: graphicswin.cpp:45
+msgid "&Save"
+msgstr "&Guardar"
+
+#: graphicswin.cpp:46
+msgid "Save &As..."
+msgstr "Guardar &Como..."
+
+#: graphicswin.cpp:48
+msgid "Export &Image..."
+msgstr "Exportar &Imagen..."
+
+#: graphicswin.cpp:49
+msgid "Export 2d &View..."
+msgstr "Exportar 2d &Vista..."
+
+#: graphicswin.cpp:50
+msgid "Export 2d &Section..."
+msgstr "Exportar 2d &Corte..."
+
+#: graphicswin.cpp:51
+msgid "Export 3d &Wireframe..."
+msgstr "Exportar 3d &Estructura alámbrica..."
+
+#: graphicswin.cpp:52
+msgid "Export Triangle &Mesh..."
+msgstr "Exportar Triángulo &Malla..."
+
+#: graphicswin.cpp:53
+msgid "Export &Surfaces..."
+msgstr "Exportar &Superficies..."
+
+#: graphicswin.cpp:54
+msgid "Im&port..."
+msgstr "Im&portar..."
+
+#: graphicswin.cpp:57
+msgid "E&xit"
+msgstr "S&alir"
+
+#: graphicswin.cpp:60
+msgid "&Edit"
+msgstr "&Editar"
+
+#: graphicswin.cpp:61
+msgid "&Undo"
+msgstr "&Deshacer"
+
+#: graphicswin.cpp:62
+msgid "&Redo"
+msgstr "&Rehacer"
+
+#: graphicswin.cpp:63
+msgid "Re&generate All"
+msgstr "Re&generar Todo"
+
+#: graphicswin.cpp:65
+msgid "Snap Selection to &Grid"
+msgstr "Selección Enganche a &Cuadrícula"
+
+#: graphicswin.cpp:66
+msgid "Rotate Imported &90°"
+msgstr "Rotar importado a &90°"
+
+#: graphicswin.cpp:68
+msgid "Cu&t"
+msgstr "Cor&tar"
+
+#: graphicswin.cpp:69
+msgid "&Copy"
+msgstr "&Copiar"
+
+#: graphicswin.cpp:70
+msgid "&Paste"
+msgstr "&Pegar"
+
+#: graphicswin.cpp:71
+msgid "Paste &Transformed..."
+msgstr "Pegar &Тransformar..."
+
+#: graphicswin.cpp:72
+msgid "&Delete"
+msgstr "&Borrar"
+
+#: graphicswin.cpp:74
+msgid "Select &Edge Chain"
+msgstr "Seleccionar Cadena de &Aristas"
+
+#: graphicswin.cpp:75
+msgid "Select &All"
+msgstr "Seleccionar &Todo"
+
+#: graphicswin.cpp:76
+msgid "&Unselect All"
+msgstr "&Deseleccionar Todo"
+
+#: graphicswin.cpp:78
+msgid "&Line Styles..."
+msgstr "Estilos de Línea..."
+
+#: graphicswin.cpp:79
+msgid "&View Projection..."
+msgstr "&Ver Proyección..."
+
+#: graphicswin.cpp:81
+msgid "Con&figuration..."
+msgstr "Con&figuración..."
+
+#: graphicswin.cpp:84
+msgid "&View"
+msgstr "&Vista"
+
+#: graphicswin.cpp:85
+msgid "Zoom &In"
+msgstr "Acer&car"
+
+#: graphicswin.cpp:86
+msgid "Zoom &Out"
+msgstr "Ale&jar"
+
+#: graphicswin.cpp:87
+msgid "Zoom To &Fit"
+msgstr " Enfoque para ajustar"
+
+#: graphicswin.cpp:89
+msgid "Align View to &Workplane"
+msgstr "Alinear Vista a &Plano de trabajo"
+
+#: graphicswin.cpp:90
+msgid "Nearest &Ortho View"
+msgstr "Vista &Ortogonal mas cercana"
+
+#: graphicswin.cpp:91
+msgid "Nearest &Isometric View"
+msgstr "Vista &Isometrica mas cercana"
+
+#: graphicswin.cpp:92
+msgid "&Center View At Point"
+msgstr "&Vista Central en Punto"
+
+#: graphicswin.cpp:94
+msgid "Show Snap &Grid"
+msgstr "Mostrar Enganches &Cuadrícula"
+
+#: graphicswin.cpp:95
+msgid "Darken Inactive Solids"
+msgstr "Oscurecer Sólidos Inactivos"
+
+#: graphicswin.cpp:96
+msgid "Use &Perspective Projection"
+msgstr "Usar Proyección &Perspectiva"
+
+#: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr ""
+
+#: graphicswin.cpp:98
+msgid "Dimension &Units"
+msgstr "&Unidades de Cota"
+
+#: graphicswin.cpp:99
+msgid "Dimensions in &Millimeters"
+msgstr "Cotas en &Milímetros"
+
+#: graphicswin.cpp:100
+msgid "Dimensions in M&eters"
+msgstr "Cotas en M&etros"
+
+#: graphicswin.cpp:101
+msgid "Dimensions in &Inches"
+msgstr "Cotas en &Pulgadas"
+
+#: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr ""
+
+#: graphicswin.cpp:104
+msgid "Show &Toolbar"
+msgstr "Mostrar &Barra de herramientas"
+
+#: graphicswin.cpp:105
+msgid "Show Property Bro&wser"
+msgstr "Mostrar Nave&gador de Propiedades"
+
+#: graphicswin.cpp:107
+msgid "&Full Screen"
+msgstr "&Pantalla Completa"
+
+#: graphicswin.cpp:109
+msgid "&New Group"
+msgstr "&Nuevo Grupo"
+
+#: graphicswin.cpp:110
+msgid "Sketch In &3d"
+msgstr "Сroquis En &3d"
+
+#: graphicswin.cpp:111
+msgid "Sketch In New &Workplane"
+msgstr "Сroquis En Nuevo &Plano de trabajo"
+
+#: graphicswin.cpp:113
+msgid "Step &Translating"
+msgstr "Paso &Traslación"
+
+#: graphicswin.cpp:114
+msgid "Step &Rotating"
+msgstr "Paso &Giratorio"
+
+#: graphicswin.cpp:116
+msgid "E&xtrude"
+msgstr "E&xtrusión"
+
+#: graphicswin.cpp:117
+msgid "&Helix"
+msgstr "&Hélice"
+
+#: graphicswin.cpp:118
+msgid "&Lathe"
+msgstr "&Torno"
+
+#: graphicswin.cpp:119
+msgid "Re&volve"
+msgstr "Re&volución"
+
+#: graphicswin.cpp:121
+msgid "Link / Assemble..."
+msgstr "Enlace / Ensamblar..."
+
+#: graphicswin.cpp:122
+msgid "Link Recent"
+msgstr "Enlace Reciente"
+
+#: graphicswin.cpp:124
+msgid "&Sketch"
+msgstr "&Croquis"
+
+#: graphicswin.cpp:125
+msgid "In &Workplane"
+msgstr "En &Plano de trabajo"
+
+#: graphicswin.cpp:126
+msgid "Anywhere In &3d"
+msgstr "En cualquier lugar en &3d"
+
+#: graphicswin.cpp:128
+msgid "Datum &Point"
+msgstr "Referencia &Punto"
+
+#: graphicswin.cpp:129
+msgid "&Workplane"
+msgstr "&Plano de trabajo"
+
+#: graphicswin.cpp:131
+msgid "Line &Segment"
+msgstr "Línea &Segmento"
+
+#: graphicswin.cpp:132
+msgid "C&onstruction Line Segment"
+msgstr "S&egmento de Línea de Construcción"
+
+#: graphicswin.cpp:133
+msgid "&Rectangle"
+msgstr "&Rectángulo"
+
+#: graphicswin.cpp:134
+msgid "&Circle"
+msgstr "&Círculo"
+
+#: graphicswin.cpp:135
+msgid "&Arc of a Circle"
+msgstr "&Arco de un Círculo"
+
+#: graphicswin.cpp:136
+msgid "&Bezier Cubic Spline"
+msgstr "&Spline Cúbico de Bezier"
+
+#: graphicswin.cpp:138
+msgid "&Text in TrueType Font"
+msgstr "&Texto en Fuente TrueType"
+
+#: graphicswin.cpp:139
+msgid "&Image"
+msgstr "&Imagen"
+
+#: graphicswin.cpp:141
+msgid "To&ggle Construction"
+msgstr "Al&ternar Construcción"
+
+#: graphicswin.cpp:142
+msgid "Tangent &Arc at Point"
+msgstr "Tangente &Arco en el Punto"
+
+#: graphicswin.cpp:143
+msgid "Split Curves at &Intersection"
+msgstr "Dividir Curvas en &Intersección"
+
+#: graphicswin.cpp:145
+msgid "&Constrain"
+msgstr "&Restricción"
+
+#: graphicswin.cpp:146
+msgid "&Distance / Diameter"
+msgstr "&Distancia / Diámetro"
+
+#: graphicswin.cpp:147
+msgid "Re&ference Dimension"
+msgstr "Co&ta de Referencia"
+
+#: graphicswin.cpp:148
+msgid "A&ngle"
+msgstr "Á&ngulo"
+
+#: graphicswin.cpp:149
+msgid "Reference An&gle"
+msgstr "Ángulo de Re&ferencia"
+
+#: graphicswin.cpp:150
+msgid "Other S&upplementary Angle"
+msgstr "Otro Á&ngulo Suplementario"
+
+#: graphicswin.cpp:151
+msgid "Toggle R&eference Dim"
+msgstr "Alternar C&ota Referencia"
+
+#: graphicswin.cpp:153
+msgid "&Horizontal"
+msgstr "&Horizontal"
+
+#: graphicswin.cpp:154
+msgid "&Vertical"
+msgstr "&Vertical"
+
+#: graphicswin.cpp:156
+msgid "&On Point / Curve / Plane"
+msgstr "&Sobre Punto / Curva / Plano"
+
+#: graphicswin.cpp:157
+msgid "E&qual Length / Radius / Angle"
+msgstr "I&gual Longitud / Radio / Ángulo"
+
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr ""
+
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr ""
+
+#: graphicswin.cpp:160
+msgid "At &Midpoint"
+msgstr "En &PuntoMedio"
+
+#: graphicswin.cpp:161
+msgid "S&ymmetric"
+msgstr "S&imetría"
+
+#: graphicswin.cpp:162
+msgid "Para&llel / Tangent"
+msgstr "Para&lela / Tangente"
+
+#: graphicswin.cpp:163
+msgid "&Perpendicular"
+msgstr "&Perpendicular"
+
+#: graphicswin.cpp:164
+msgid "Same Orient&ation"
+msgstr "Misma Orient&ación"
+
+#: graphicswin.cpp:165
+msgid "Lock Point Where &Dragged"
+msgstr "Punto de Bloqueo Donde &Arrastrado"
+
+#: graphicswin.cpp:167
+msgid "Comment"
+msgstr "Comentario"
+
+#: graphicswin.cpp:169
+msgid "&Analyze"
+msgstr "&Analizar"
+
+#: graphicswin.cpp:170
+msgid "Measure &Volume"
+msgstr "Medición &Volumen"
+
+#: graphicswin.cpp:171
+msgid "Measure A&rea"
+msgstr "Medición Á&rea"
+
+#: graphicswin.cpp:172
+msgid "Measure &Perimeter"
+msgstr "Medición &Perímetro"
+
+#: graphicswin.cpp:173
+msgid "Show &Interfering Parts"
+msgstr "Mostrar &Piezas que Interfieren"
+
+#: graphicswin.cpp:174
+msgid "Show &Naked Edges"
+msgstr "Mostrar &Aristas Desnudas"
+
+#: graphicswin.cpp:175
+msgid "Show &Center of Mass"
+msgstr "Mostrar &Centro de Masa"
+
+#: graphicswin.cpp:177
+msgid "Show &Underconstrained Points"
+msgstr "Mostrar &Puntos Subrestringidos"
+
+#: graphicswin.cpp:179
+msgid "&Trace Point"
+msgstr "&Punto de Rastro"
+
+#: graphicswin.cpp:180
+msgid "&Stop Tracing..."
+msgstr "&Dejar de rastrear..."
+
+#: graphicswin.cpp:181
+msgid "Step &Dimension..."
+msgstr "Cota &Paso..."
+
+#: graphicswin.cpp:183
+msgid "&Help"
+msgstr "&Ayuda"
+
+#: graphicswin.cpp:184
+msgid "&Language"
+msgstr "&Lenguaje"
+
+#: graphicswin.cpp:185
+msgid "&Website / Manual"
+msgstr "&Sitio Web / Manual"
+
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
+msgid "&About"
+msgstr "&Acerca"
+
+#: graphicswin.cpp:362
+msgid "(no recent files)"
+msgstr "(no hay archivos recientes)"
+
+#: graphicswin.cpp:370
+#, c-format
+msgid "File '%s' does not exist."
+msgstr "El archivo '%s' no existe."
+
+#: graphicswin.cpp:737
+msgid "No workplane is active, so the grid will not appear."
+msgstr ""
+"No hay ningún plano de trabajo activo, por lo que la cuadrícula no aparecerá."
+
+#: graphicswin.cpp:752
+msgid ""
+"The perspective factor is set to zero, so the view will always be a parallel "
+"projection.\n"
+"\n"
+"For a perspective projection, modify the perspective factor in the "
+"configuration screen. A value around 0.3 is typical."
+msgstr ""
+"El factor de perspectiva se establece en cero, por lo que la vista siempre "
+"será una proyección paralela.\n"
+"\n"
+"Para una proyección en perspectiva, modifique el factor de perspectiva en la "
+"pantalla de configuración.  Un valor de alrededor de 0,3 es típico."
+
+#: graphicswin.cpp:837
+msgid ""
+"Select a point; this point will become the center of the view on screen."
+msgstr ""
+"Seleccione un punto; este punto se convertirá en el centro de la vista en "
+"pantalla."
+
+#: graphicswin.cpp:1137
+msgid "No additional entities share endpoints with the selected entities."
+msgstr ""
+"Ninguna entidad adicional comparte puntos finales con las entidades "
+"seleccionadas."
+
+#: graphicswin.cpp:1155
+msgid ""
+"To use this command, select a point or other entity from an linked part, or "
+"make a link group the active group."
+msgstr ""
+"Para usar este comando, seleccione un punto u otra entidad de una parte "
+"vinculada, o convertir un grupo de enlaces en el grupo activo."
+
+#: graphicswin.cpp:1178
+msgid ""
+"No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
+"to define the plane for the snap grid."
+msgstr ""
+"No hay ningún plano de trabajo activo. Activar un plano de trabajo (con "
+"Croquis -> En plano de trabajo) para definir el plano para el enganche a la "
+"cuadrícula."
+
+#: graphicswin.cpp:1185
+msgid ""
+"Can't snap these items to grid; select points, text comments, or constraints "
+"with a label. To snap a line, select its endpoints."
+msgstr ""
+"No se pueden enganchar estos elementos a la cuadrícula; seleccionar puntos, "
+"comentarios de texto o restricciones con una etiqueta. Para enganchar una "
+"línea, seleccione sus puntos finales."
+
+#: graphicswin.cpp:1270
+msgid "No workplane selected. Activating default workplane for this group."
+msgstr ""
+"No se seleccionó ningún plano de trabajo. Activando el plano de trabajo "
+"predeterminado para este grupo."
+
+#: graphicswin.cpp:1273
+msgid ""
+"No workplane is selected, and the active group does not have a default "
+"workplane. Try selecting a workplane, or activating a sketch-in-new-"
+"workplane group."
+msgstr ""
+"No se selecciona ningún plano de trabajo y el grupo activo no tiene un plano "
+"de trabajo. Intente seleccionar un plano de trabajo o activar un croquis-en-"
+"nuevo-grupo de plano de trabajo."
+
+#: graphicswin.cpp:1294
+msgid ""
+"Bad selection for tangent arc at point. Select a single point, or select "
+"nothing to set up arc parameters."
+msgstr ""
+"Mala selección de arco tangente en el punto. Seleccione un solo punto o no "
+"seleccione nada para configurar los parámetros del arco."
+
+#: graphicswin.cpp:1305
+msgid "click point on arc (draws anti-clockwise)"
+msgstr "clic en el punto en el arco (dibuja en sentido antihorario)"
+
+#: graphicswin.cpp:1306
+msgid "click to place datum point"
+msgstr "clic para colocar el punto de referencia"
+
+#: graphicswin.cpp:1307
+msgid "click first point of line segment"
+msgstr "clic en el primer punto del segmento de línea"
+
+#: graphicswin.cpp:1309
+msgid "click first point of construction line segment"
+msgstr "clic en el primer punto del segmento de línea de construcción"
+
+#: graphicswin.cpp:1310
+msgid "click first point of cubic segment"
+msgstr "clic en el primer punto del segmento cúbico"
+
+#: graphicswin.cpp:1311
+msgid "click center of circle"
+msgstr "clic en el centro del círculo"
+
+#: graphicswin.cpp:1312
+msgid "click origin of workplane"
+msgstr "clic en origen del plano de trabajo"
+
+#: graphicswin.cpp:1313
+msgid "click one corner of rectangle"
+msgstr "clic en una esquina del rectángulo"
+
+#: graphicswin.cpp:1314
+msgid "click top left of text"
+msgstr "clic en la parte superior izquierda del texto"
+
+#: graphicswin.cpp:1320
+msgid "click top left of image"
+msgstr "clic en la parte superior izquierda de la imagen"
+
+#: graphicswin.cpp:1346
+msgid ""
+"No entities are selected. Select entities before trying to toggle their "
+"construction state."
+msgstr ""
+"No se seleccionaron entidades. Seleccione entidades antes de intentar "
+"alternar su estado de construcción."
+
+#: group.cpp:86
+msgctxt "group-name"
+msgid "sketch-in-3d"
+msgstr "croquis-en-3d"
+
+#: group.cpp:150
+msgid ""
+"Bad selection for new sketch in workplane. This group can be created with:\n"
+"\n"
+"    * a point (through the point, orthogonal to coordinate axes)\n"
+"    * a point and two line segments (through the point, parallel to the "
+"lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
+"    * a workplane (copy of the workplane)\n"
+msgstr ""
+
+#: group.cpp:166
+msgid ""
+"Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
+"will be extruded normal to the workplane."
+msgstr ""
+"Active un plano de trabajo (Croquis -> En plano de trabajo) antes de "
+"extruir. El croquis se extruirá normal al plano de trabajo."
+
+#: group.cpp:175
+msgctxt "group-name"
+msgid "extrude"
+msgstr "extruir"
+
+#: group.cpp:180
+msgid "Lathe operation can only be applied to planar sketches."
+msgstr "La operación de torno solo se puede aplicar a croquis planos."
+
+#: group.cpp:191
+msgid ""
+"Bad selection for new lathe group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Mala selección para el nuevo grupo de torno. Este grupo se puede crear con:\n"
+"\n"
+"    * un punto y un segmento de línea o normal (revolucionado alrededor de "
+"un eje paralelo a la línea / normal, a través del punto)\n"
+"    * un segmento de línea (revolucionado sobre un segmento de línea)\n"
+
+#: group.cpp:201
+msgctxt "group-name"
+msgid "lathe"
+msgstr "torno"
+
+#: group.cpp:206
+msgid "Revolve operation can only be applied to planar sketches."
+msgstr "La operación de revolución solo se puede aplicar a croquis planos."
+
+#: group.cpp:217
+msgid ""
+"Bad selection for new revolve group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Mala selección para el nuevo grupo de revolución. Este grupo se puede crear "
+"con:\n"
+"\n"
+"    * un punto y un segmento de línea o normal (revolucionado alrededor de "
+"un eje paralelo a la línea / normal, a través del punto)\n"
+"    * un segmento de línea (revolucionado sobre un segmento de línea)\n"
+
+#: group.cpp:229
+msgctxt "group-name"
+msgid "revolve"
+msgstr "revolución"
+
+#: group.cpp:234
+msgid "Helix operation can only be applied to planar sketches."
+msgstr "La operación de hélice solo se puede aplicar a croquis planos."
+
+#: group.cpp:245
+msgid ""
+"Bad selection for new helix group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Mala selección para el nuevo grupo de hélice. Este grupo se puede crear "
+"con:\n"
+"\n"
+"    * un punto y un segmento de recta o normal (girado alrededor de un eje "
+"paralelo a la línea / normal, a través del punto)\n"
+"    * un segmento de línea (girado sobre un segmento de línea)\n"
+
+#: group.cpp:257
+msgctxt "group-name"
+msgid "helix"
+msgstr "hélice"
+
+#: group.cpp:270
+msgid ""
+"Bad selection for new rotation. This group can be created with:\n"
+"\n"
+"    * a point, while locked in workplane (rotate in plane, about that "
+"point)\n"
+"    * a point and a line or a normal (rotate about an axis through the "
+"point, and parallel to line / normal)\n"
+msgstr ""
+"Mala selección para nueva rotación. Este grupo se puede crear con:\n"
+"\n"
+"    * un punto, mientras está bloqueado en el plano de trabajo (girar en el "
+"plano, sobre ese punto)\n"
+"    * un punto y una línea o una normal (rotar alrededor de un eje a través "
+"de un punto y paralela a la línea / normal)\n"
+
+#: group.cpp:283
+msgctxt "group-name"
+msgid "rotate"
+msgstr "rotar"
+
+#: group.cpp:294
+msgctxt "group-name"
+msgid "translate"
+msgstr "trasladar"
+
+#: group.cpp:416
+msgid "(unnamed)"
+msgstr "(sin nombre)"
+
+#: groupmesh.cpp:707
+msgid "not closed contour, or not all same style!"
+msgstr "¡Contorno no cerrado, o no todos del mismo estilo!"
+
+#: groupmesh.cpp:720
+msgid "points not all coplanar!"
+msgstr "¡No todos los puntos son coplanares!"
+
+#: groupmesh.cpp:722
+msgid "contour is self-intersecting!"
+msgstr "¡El contorno se intersecta a sí mismo!"
+
+#: groupmesh.cpp:724
+msgid "zero-length edge!"
+msgstr "¡arista de longitud cero!"
+
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr ""
+
+#: modify.cpp:252
+msgid "Must be sketching in workplane to create tangent arc."
+msgstr ""
+"Debe estar dibujando en el plano de trabajo para crear un arco tangente."
+
+#: modify.cpp:299
+msgid ""
+"To create a tangent arc, select a point where two non-construction lines or "
+"circles in this group and workplane join."
+msgstr ""
+"Para crear un arco tangente, seleccione un punto donde dos líneas que no "
+"sean de construcción o los círculos de este grupo y el plano de trabajo se "
+"unen."
+
+#: modify.cpp:386
+msgid ""
+"Couldn't round this corner. Try a smaller radius, or try creating the "
+"desired geometry by hand with tangency constraints."
+msgstr ""
+"No pude redondear esta esquina. Pruebe con un radio más pequeño o intente "
+"crear la geometría deseada a mano con restricciones de tangencia."
+
+#: modify.cpp:595
+msgid "Couldn't split this entity; lines, circles, or cubics only."
+msgstr "No se pudo dividir esta entidad; solo líneas, círculos o cúbicos."
+
+#: modify.cpp:622
+msgid "Must be sketching in workplane to split."
+msgstr "Debe estar dibujando en el plano de trabajo para dividir."
+
+#: modify.cpp:629
+msgid ""
+"Select two entities that intersect each other (e.g. two lines/circles/arcs "
+"or a line/circle/arc and a point)."
+msgstr ""
+"Seleccione dos entidades que se crucen entre sí (por ejemplo, dos líneas / "
+"círculos / arcos o una línea / círculo / arco y un punto)."
+
+#: modify.cpp:734
+msgid "Can't split; no intersection found."
+msgstr "No se puede dividir; no se encontró ninguna intersección."
+
+#: mouse.cpp:557
+msgid "Assign to Style"
+msgstr "Asignar a Estilo"
+
+#: mouse.cpp:573
+msgid "No Style"
+msgstr "Sin Estilo"
+
+#: mouse.cpp:576
+msgid "Newly Created Custom Style..."
+msgstr "Estilo Personalizado Recién Creado..."
+
+#: mouse.cpp:583
+msgid "Group Info"
+msgstr "Información de Grupo"
+
+#: mouse.cpp:603
+msgid "Style Info"
+msgstr "Información de Estilo"
+
+#: mouse.cpp:623
+msgid "Select Edge Chain"
+msgstr "Seleccionar Cadena de Arista"
+
+#: mouse.cpp:629
+msgid "Toggle Reference Dimension"
+msgstr "Alternar Cota de Referencia"
+
+#: mouse.cpp:635
+msgid "Other Supplementary Angle"
+msgstr "Otro Ángulo Suplementario"
+
+#: mouse.cpp:640
+msgid "Snap to Grid"
+msgstr "Enganchar a la cuadrícula"
+
+#: mouse.cpp:649
+msgid "Remove Spline Point"
+msgstr "Remover Punto de Spline"
+
+#: mouse.cpp:684
+msgid "Add Spline Point"
+msgstr "Agregar Punto de Spline"
+
+#: mouse.cpp:688
+msgid "Cannot add spline point: maximum number of points reached."
+msgstr ""
+"No se puede agregar un punto de spline: se alcanzó el número máximo de "
+"puntos."
+
+#: mouse.cpp:713
+msgid "Toggle Construction"
+msgstr "Alternar Construcción"
+
+#: mouse.cpp:729
+msgid "Delete Point-Coincident Constraint"
+msgstr "Eliminar restricción de punto-coincidente"
+
+#: mouse.cpp:747
+msgid "Cut"
+msgstr "Cortar"
+
+#: mouse.cpp:749
+msgid "Copy"
+msgstr "Copiar"
+
+#: mouse.cpp:753
+msgid "Select All"
+msgstr "Seleccionar Todo "
+
+#: mouse.cpp:758
+msgid "Paste"
+msgstr "Pegar"
+
+#: mouse.cpp:760
+msgid "Paste Transformed..."
+msgstr "Pegar Transformado ..."
+
+#: mouse.cpp:765
+msgid "Delete"
+msgstr "Eliminar"
+
+#: mouse.cpp:768
+msgid "Unselect All"
+msgstr "Deseleccionar Todo"
+
+#: mouse.cpp:775
+msgid "Unselect Hovered"
+msgstr "Deselección Flotante"
+
+#: mouse.cpp:784
+msgid "Zoom to Fit"
+msgstr "Zoom para ajustar"
+
+#: mouse.cpp:986 mouse.cpp:1274
+msgid "click next point of line, or press Esc"
+msgstr "clic en el siguiente punto de la línea o presione Esc"
+
+#: mouse.cpp:992
+msgid ""
+"Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"No se puede dibujar un rectángulo en 3d; primero, active un plano de trabajo "
+"con Croquis -> En Plano de trabajo."
+
+#: mouse.cpp:1026
+msgid "click to place other corner of rectangle"
+msgstr "clic para colocar la otra esquina del rectángulo"
+
+#: mouse.cpp:1047
+msgid "click to set radius"
+msgstr "clic para establecer el radio"
+
+#: mouse.cpp:1052
+msgid ""
+"Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"No se puede dibujar un arco en 3d; primero, active un plano de trabajo con "
+"Croquis -> En Plano de trabajo."
+
+#: mouse.cpp:1071
+msgid "click to place point"
+msgstr "clic para colocar el punto"
+
+#: mouse.cpp:1087
+msgid "click next point of cubic, or press Esc"
+msgstr "clic en el siguiente punto del cúbico, o presione Esc"
+
+#: mouse.cpp:1092
+msgid ""
+"Sketching in a workplane already; sketch in 3d before creating new workplane."
+msgstr ""
+"Dibujando en un plano de trabajo ya; croquis en 3d antes de crear un nuevo "
+"plano de trabajo."
+
+#: mouse.cpp:1108
+msgid ""
+"Can't draw text in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"No se puede dibujar texto en 3D; primero, active un plano de trabajo con "
+"Croquis -> En Plano de trabajo."
+
+#: mouse.cpp:1125
+msgid "click to place bottom right of text"
+msgstr "clic para colocar la parte inferior derecha del texto"
+
+#: mouse.cpp:1131
+msgid ""
+"Can't draw image in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"No se puede dibujar una imagen en 3D; primero, active un plano de trabajo "
+"con Croquis -> En Plano de Trabajo."
+
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
+msgctxt "file-type"
+msgid "SolveSpace models"
+msgstr "SolveSpace modelos"
+
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr ""
+
+#: platform/gui.cpp:91
+msgctxt "file-type"
+msgid "IDF circuit board"
+msgstr "placa circuito IDF"
+
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr ""
+
+#: platform/gui.cpp:96
+msgctxt "file-type"
+msgid "PNG image"
+msgstr "imagen PNG"
+
+#: platform/gui.cpp:100
+msgctxt "file-type"
+msgid "STL mesh"
+msgstr "STL malla"
+
+#: platform/gui.cpp:101
+msgctxt "file-type"
+msgid "Wavefront OBJ mesh"
+msgstr "Wavefront OBJ malla"
+
+#: platform/gui.cpp:102
+msgctxt "file-type"
+msgid "Three.js-compatible mesh, with viewer"
+msgstr "Three.js-malla compatible, con visor"
+
+#: platform/gui.cpp:103
+msgctxt "file-type"
+msgid "Three.js-compatible mesh, mesh only"
+msgstr "Three.js-malla compatible, solo malla"
+
+#: platform/gui.cpp:104
+msgctxt "file-type"
+msgid "VRML text file"
+msgstr "Archivo texto VRML"
+
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
+msgctxt "file-type"
+msgid "STEP file"
+msgstr "Archivo STEP"
+
+#: platform/gui.cpp:112
+msgctxt "file-type"
+msgid "PDF file"
+msgstr "Archivo PDF"
+
+#: platform/gui.cpp:113
+msgctxt "file-type"
+msgid "Encapsulated PostScript"
+msgstr "Encapsulado PostScript"
+
+#: platform/gui.cpp:114
+msgctxt "file-type"
+msgid "Scalable Vector Graphics"
+msgstr "Gráficos Vectoriales Escalables"
+
+#: platform/gui.cpp:116 platform/gui.cpp:123
+msgctxt "file-type"
+msgid "DXF file (AutoCAD 2007)"
+msgstr "Archivo DXF (AutoCAD 2007)"
+
+#: platform/gui.cpp:117
+msgctxt "file-type"
+msgid "HPGL file"
+msgstr "Archivo HPGL"
+
+#: platform/gui.cpp:118
+msgctxt "file-type"
+msgid "G Code"
+msgstr "G Code"
+
+#: platform/gui.cpp:127
+msgctxt "file-type"
+msgid "AutoCAD DXF and DWG files"
+msgstr "Archivos AutoCAD DXF y DWG"
+
+#: platform/gui.cpp:131
+msgctxt "file-type"
+msgid "Comma-separated values"
+msgstr "Valores separados por comas"
+
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
+msgid "untitled"
+msgstr "sin título"
+
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
+msgctxt "title"
+msgid "Save File"
+msgstr "Guardar Archivo"
+
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
+msgctxt "title"
+msgid "Open File"
+msgstr "Abrir Archivo"
+
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
+msgctxt "button"
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
+msgctxt "button"
+msgid "_Save"
+msgstr "_Guardar"
+
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
+msgctxt "button"
+msgid "_Open"
+msgstr "_Abrir"
+
+#: solvespace.cpp:171
+msgctxt "title"
+msgid "Autosave Available"
+msgstr "Autoguardado Disponible"
+
+#: solvespace.cpp:172
+msgctxt "dialog"
+msgid "An autosave file is available for this sketch."
+msgstr "Un archivo de autoguardado está disponible para este croquis."
+
+#: solvespace.cpp:173
+msgctxt "dialog"
+msgid "Do you want to load the autosave file instead?"
+msgstr "¿Desea cargar el archivo de autoguardado en su lugar?"
+
+#: solvespace.cpp:174
+msgctxt "button"
+msgid "&Load autosave"
+msgstr "&Cargar autoguardado"
+
+#: solvespace.cpp:176
+msgctxt "button"
+msgid "Do&n't Load"
+msgstr "No Cargar"
+
+#: solvespace.cpp:599
+msgctxt "title"
+msgid "Modified File"
+msgstr "Archivo Modificado"
+
+#: solvespace.cpp:601
+#, c-format
+msgctxt "dialog"
+msgid "Do you want to save the changes you made to the sketch “%s”?"
+msgstr "¿Desea guardar los cambios que realizó en el croquis “%s”?"
+
+#: solvespace.cpp:604
+msgctxt "dialog"
+msgid "Do you want to save the changes you made to the new sketch?"
+msgstr "¿Desea guardar los cambios que realizó en el nuevo croquis?"
+
+#: solvespace.cpp:607
+msgctxt "dialog"
+msgid "Your changes will be lost if you don't save them."
+msgstr "Sus cambios se perderán si no los guarda."
+
+#: solvespace.cpp:608
+msgctxt "button"
+msgid "&Save"
+msgstr "&Guardar"
+
+#: solvespace.cpp:610
+msgctxt "button"
+msgid "Do&n't Save"
+msgstr "No& Guardar"
+
+#: solvespace.cpp:631
+msgctxt "title"
+msgid "(new sketch)"
+msgstr "(nuevo croquis)"
+
+#: solvespace.cpp:638
+msgctxt "title"
+msgid "Property Browser"
+msgstr "Explorador de Propiedades"
+
+#: solvespace.cpp:700
+msgid ""
+"Constraints are currently shown, and will be exported in the toolpath. This "
+"is probably not what you want; hide them by clicking the link at the top of "
+"the text window."
+msgstr ""
+"Las restricciones se muestran actualmente y se exportarán en la trayectoria."
+"Probablemente esto no sea lo que quieres; ocultarlos haciendo clic en el "
+"enlace en la parte superior de la ventana de texto."
+
+#: solvespace.cpp:772
+#, c-format
+msgid ""
+"Can't identify file type from file extension of filename '%s'; try .dxf or ."
+"dwg."
+msgstr ""
+"No se puede identificar el tipo de archivo a partir de la extensión del "
+"nombre del archivo '%s'; intente .dxf o .dwg."
+
+#: solvespace.cpp:824
+msgid "Constraint must have a label, and must not be a reference dimension."
+msgstr ""
+"La restricción debe tener una etiqueta y no debe ser una cota de referencia."
+
+#: solvespace.cpp:828
+msgid "Bad selection for step dimension; select a constraint."
+msgstr "Mala selección para la cota del paso; seleccione una restricción."
+
+#: solvespace.cpp:852
+msgid "The assembly does not interfere, good."
+msgstr "El ensamble no interfiere, bien."
+
+#: solvespace.cpp:868
+#, c-format
+msgid ""
+"The volume of the solid model is:\n"
+"\n"
+"    %s"
+msgstr ""
+"El volumen del modelo sólido es:\n"
+"\n"
+"    %s"
+
+#: solvespace.cpp:877
+#, c-format
+msgid ""
+"\n"
+"The volume of current group mesh is:\n"
+"\n"
+"    %s"
+msgstr ""
+"\n"
+"El volumen de la malla del grupo actual es:\n"
+"\n"
+"    %s"
+
+#: solvespace.cpp:882
+msgid ""
+"\n"
+"\n"
+"Curved surfaces have been approximated as triangles.\n"
+"This introduces error, typically of around 1%."
+msgstr ""
+"\n"
+"\n"
+"Las superficies curvas se han aproximado como triángulos.\n"
+"Esto introduce un error, normalmente alrededor del 1%."
+
+#: solvespace.cpp:897
+#, c-format
+msgid ""
+"The surface area of the selected faces is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"El área de la superficie de las caras seleccionadas es:\n"
+"\n"
+"    %s\n"
+"\n"
+"Las curvas se han aproximado como lineales por partes.\n"
+"Esto introduce un error, normalmente alrededor del 1%%."
+
+#: solvespace.cpp:906
+msgid ""
+"This group does not contain a correctly-formed 2d closed area. It is open, "
+"not coplanar, or self-intersecting."
+msgstr ""
+"Este grupo no contiene un área cerrada 2d correctamente formada. Está "
+"abierta, no coplanares, ni auto-intersectantes."
+
+#: solvespace.cpp:918
+#, c-format
+msgid ""
+"The area of the region sketched in this group is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"El área de la región croquizada en este grupo es:\n"
+"\n"
+"    %s\n"
+"\n"
+"Las curvas se han aproximado como lineales por partes.\n"
+"Esto introduce un error, normalmente alrededor del 1%%."
+
+#: solvespace.cpp:938
+#, c-format
+msgid ""
+"The total length of the selected entities is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"La longitud total de las entidades seleccionadas es:\n"
+"\n"
+"    %s\n"
+"\n"
+"Las curvas se han aproximado como lineales por partes.\n"
+"Esto introduce un error, normalmente alrededor del 1%%."
+
+#: solvespace.cpp:944
+msgid "Bad selection for perimeter; select line segments, arcs, and curves."
+msgstr ""
+"Mala selección de perímetro; seleccione segmentos de línea, arcos y curvas."
+
+#: solvespace.cpp:960
+msgid "Bad selection for trace; select a single point."
+msgstr "Mala selección de rastreo; seleccione un solo punto."
+
+#: solvespace.cpp:987
+#, c-format
+msgid "Couldn't write to '%s'"
+msgstr "No pude escribir a '%s'"
+
+#: solvespace.cpp:1017
+msgid "The mesh is self-intersecting (NOT okay, invalid)."
+msgstr "La malla se intersecta a si misma (NO está bien, no es válida)."
+
+#: solvespace.cpp:1018
+msgid "The mesh is not self-intersecting (okay, valid)."
+msgstr "La malla no se intersecta (está bien, es válida)."
+
+#: solvespace.cpp:1020
+msgid "The mesh has naked edges (NOT okay, invalid)."
+msgstr "La malla tiene bordes desnudos (NO está bien, no es válida)."
+
+#: solvespace.cpp:1021
+msgid "The mesh is watertight (okay, valid)."
+msgstr "La malla es estanca (está bien, es válida)."
+
+#: solvespace.cpp:1024
+#, c-format
+msgid ""
+"\n"
+"\n"
+"The model contains %d triangles, from %d surfaces."
+msgstr ""
+"\n"
+"\n"
+"El modelo contiene %d triángulos, desde %d superficies."
+
+#: solvespace.cpp:1028
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Zero problematic edges, good.%s"
+msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Cero aristas problemáticas, bien.%s"
+
+#: solvespace.cpp:1031
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d problematic edges, bad.%s"
+msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d aristas problemáticas, mal.%s"
+
+#: solvespace.cpp:1044
+#, c-format
+msgid ""
+"This is SolveSpace version %s.\n"
+"\n"
+"For more information, see http://solvespace.com/\n"
+"\n"
+"SolveSpace is free software: you are free to modify\n"
+"and/or redistribute it under the terms of the GNU\n"
+"General Public License (GPL) version 3 or later.\n"
+"\n"
+"There is NO WARRANTY, to the extent permitted by\n"
+"law. For details, visit http://gnu.org/licenses/\n"
+"\n"
+"© 2008-%d Jonathan Westhues and other authors.\n"
+msgstr ""
+"Esta es la versión de SolveSpace %s.\n"
+"\n"
+"Para más información, ver http://solvespace.com/\n"
+"\n"
+"SolveSpace es software libre: eres libre de modificarlo\n"
+"y/o redistribuirlo bajo los términos de la GNU\n"
+"Licencia Pública General (GPL) version 3 o posterior.\n"
+"\n"
+"NO HAY GARANTÍA, en la medida permitida por\n"
+"ley. Para detalles, visita http://gnu.org/licenses/\n"
+"\n"
+"© 2008-%d Jonathan Westhues y otros autores.\n"
+
+#: style.cpp:185
+msgid ""
+"Can't assign style to an entity that's derived from another entity; try "
+"assigning a style to this entity's parent."
+msgstr ""
+"No se puede asignar estilo a una entidad derivada de otra entidad;; intente "
+"asignar un estilo al padre de esta entidad."
+
+#: style.cpp:735
+msgid "Style name cannot be empty"
+msgstr "El nombre del estilo no puede estar vacío"
+
+#: textscreens.cpp:791
+msgid "Can't repeat fewer than 1 time."
+msgstr "No se puede repetir menos de 1 vez."
+
+#: textscreens.cpp:795
+msgid "Can't repeat more than 999 times."
+msgstr "No se puede repetir más de 999 veces."
+
+#: textscreens.cpp:820
+msgid "Group name cannot be empty"
+msgstr "El nombre del grupo no puede estar vacío"
+
+#: textscreens.cpp:872
+msgid "Opacity must be between zero and one."
+msgstr "La opacidad debe estar entre cero y uno."
+
+#: textscreens.cpp:907
+msgid "Radius cannot be zero or negative."
+msgstr "El radio no puede ser cero o negativo."
+
+#: toolbar.cpp:18
+msgid "Sketch line segment"
+msgstr "Croquizar segmento de línea"
+
+#: toolbar.cpp:20
+msgid "Sketch rectangle"
+msgstr "Croquizar rectángulo"
+
+#: toolbar.cpp:22
+msgid "Sketch circle"
+msgstr "Croquizar círculo"
+
+#: toolbar.cpp:24
+msgid "Sketch arc of a circle"
+msgstr "Croquizar arco de un círculo"
+
+#: toolbar.cpp:26
+msgid "Sketch curves from text in a TrueType font"
+msgstr "Croquizar curvas desde texto en fuente TrueType"
+
+#: toolbar.cpp:28
+msgid "Sketch image from a file"
+msgstr "Croquizar imagen desde un archivo"
+
+#: toolbar.cpp:30
+msgid "Create tangent arc at selected point"
+msgstr "Crear arco tangente en el punto seleccionado"
+
+#: toolbar.cpp:32
+msgid "Sketch cubic Bezier spline"
+msgstr "Croquizar spline de Bezier cúbico"
+
+#: toolbar.cpp:34
+msgid "Sketch datum point"
+msgstr "Croquizar punto de referencia"
+
+#: toolbar.cpp:36
+msgid "Toggle construction"
+msgstr "Alternar construcción"
+
+#: toolbar.cpp:38
+msgid "Split lines / curves where they intersect"
+msgstr "Dividir líneas / curvas donde se intersectan"
+
+#: toolbar.cpp:42
+msgid "Constrain distance / diameter / length"
+msgstr "Restringir distancia / diámetro / longitud"
+
+#: toolbar.cpp:44
+msgid "Constrain angle"
+msgstr "Restringir ángulo"
+
+#: toolbar.cpp:46
+msgid "Constrain to be horizontal"
+msgstr "Restringir para ser horizontal"
+
+#: toolbar.cpp:48
+msgid "Constrain to be vertical"
+msgstr "Restringir para ser vertical"
+
+#: toolbar.cpp:50
+msgid "Constrain to be parallel or tangent"
+msgstr "Restringir para ser paralela o tangente"
+
+#: toolbar.cpp:52
+msgid "Constrain to be perpendicular"
+msgstr "Restringir para ser perpendicular"
+
+#: toolbar.cpp:54
+msgid "Constrain point on line / curve / plane / point"
+msgstr "Restringir punto en línea / curva / plano / punto"
+
+#: toolbar.cpp:56
+msgid "Constrain symmetric"
+msgstr "Restringir simétrico"
+
+#: toolbar.cpp:58
+msgid "Constrain equal length / radius / angle"
+msgstr "Restringir igualdad longitud / radio / ángulo"
+
+#: toolbar.cpp:60
+msgid "Constrain normals in same orientation"
+msgstr "Restringir normales en la misma orientación"
+
+#: toolbar.cpp:62
+msgid "Other supplementary angle"
+msgstr "Otro ángulo suplementario"
+
+#: toolbar.cpp:64
+msgid "Toggle reference dimension"
+msgstr "Alternar cota de referencia"
+
+#: toolbar.cpp:68
+msgid "New group extruding active sketch"
+msgstr "Nuevo grupo de extrusión de croquis activo"
+
+#: toolbar.cpp:70
+msgid "New group rotating active sketch"
+msgstr "Nuevo croquis activo giratorio de grupo"
+
+#: toolbar.cpp:72
+msgid "New group helix from active sketch"
+msgstr "Nueva hélice de grupo a partir del croquis activo"
+
+#: toolbar.cpp:74
+msgid "New group revolve active sketch"
+msgstr "Nuevo croquis activo de revolución de grupo"
+
+#: toolbar.cpp:76
+msgid "New group step and repeat rotating"
+msgstr "Nuevo paso de grupo y rotación repetida"
+
+#: toolbar.cpp:78
+msgid "New group step and repeat translating"
+msgstr "Nuevo paso de grupo y traslación repetida"
+
+#: toolbar.cpp:80
+msgid "New group in new workplane (thru given entities)"
+msgstr "Nuevo grupo en nuevo plano de trabajo (a través de entidades dadas)"
+
+#: toolbar.cpp:82
+msgid "New group in 3d"
+msgstr "Nuevo grupo en 3d"
+
+#: toolbar.cpp:84
+msgid "New group linking / assembling file"
+msgstr "Nuevo enlace de grupo / archivo de ensamble"
+
+#: toolbar.cpp:88
+msgid "Nearest isometric view"
+msgstr "Vista isométrica más cercana"
+
+#: toolbar.cpp:90
+msgid "Align view to active workplane"
+msgstr "Alinear vista al plano de trabajo activo"
+
+#: util.cpp:165
+msgctxt "title"
+msgid "Error"
+msgstr "Error"
+
+#: util.cpp:165
+msgctxt "title"
+msgid "Message"
+msgstr "Mensaje"
+
+#: util.cpp:170
+msgctxt "button"
+msgid "&OK"
+msgstr "&Aceptar"
+
+#: view.cpp:127
+msgid "Scale cannot be zero or negative."
+msgstr "La escala no debe ser cero o negativa."
+
+#: view.cpp:139 view.cpp:148
+msgid "Bad format: specify x, y, z"
+msgstr "Formato incorrecto: especifica x, y, z"
+
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Mala selección por restricción de la relación de longitud. Esta "
+#~ "restricción se puede aplicar a:\n"
+#~ "\n"
+#~ "    * dos segmentos de línea\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Mala selección por restricción de diferencia de longitud. Esta "
+#~ "restricción puede aplicar a:\n"
+#~ "\n"
+#~ "    * dos segmentos de línea\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "Relación Lo&ngitud"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "Diferencia Long&itud"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Mala selección para un nuevo croquis en el plano de trabajo. Este grupo "
+#~ "se puede crear con:\n"
+#~ "\n"
+#~ "    * un punto (a través del punto, ortogonal a los ejes de coordenadas)\n"
+#~ "    * un punto y dos segmentos de línea (a través del punto, paralelo a "
+#~ "líneas)\n"
+#~ "    * un plano de trabajo (copia de un plano de trabajo)\n"
+
+#~ msgctxt "file-type"
+#~ msgid "Q3D Object file"
+#~ msgstr "Archivo Objeto Q3D"
index 784b961022358246132246336db71f662537a086..ec6d3bac1fd75ffc3a2563f8fab06fa605f0a8ee 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
 "PO-Revision-Date: 2018-07-14 06:12+0000\n"
 "Last-Translator: whitequark <whitequark@whitequark.org>\n"
 "Language-Team: none\n"
@@ -17,7 +17,7 @@ msgstr ""
 "X-Generator: Zanata 4.4.5\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
@@ -27,27 +27,27 @@ msgstr ""
 "\n"
 "Activez un plan avec \"Dessin -> Dans plan de travail\"."
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr "Presse papier vide; rien à coller."
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr "Le nombre de copies à coller doit être d'au moins un."
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr "L'échelle ne peut pas être zéro."
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr "Sélectionnez un point pour définir l'origine de la rotation."
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr "Sélectionnez deux points pour définir le vecteur de translation."
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
@@ -55,23 +55,23 @@ msgstr ""
 "Transformation identique. Donc, toutes les copies seront exactement les unes "
 "au-dessus des autres."
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr "Trop d'éléments à coller; Divisez-les en plus petits groupes."
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr "Pas d'espace de travail actif."
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr "Mauvais format: spécifiez les coordonnées comme x, y, z"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr "Mauvais format; spécifiez la couleur comme r, v, b"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
@@ -79,26 +79,26 @@ msgstr ""
 "Le facteur de perspective n'aura aucun effet tant que vous n'aurez pas "
 "activé \"Affichage -> Utiliser la projection de perspective\"."
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr ""
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr "L'échelle d'export ne doit pas être zéro!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr "Le décalage du rayon de coupe ne doit pas être négatif!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr ""
 "Mauvaise valeur: l'intervalle d'enregistrement automatique devrait être "
 "positif"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr "Mauvais format: spécifiez un nombre entier de minutes"
 
@@ -169,115 +169,135 @@ msgstr "longueur-ratio"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr ""
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr ""
+
+#: constraint.cpp:27
+msgctxt "constr-name"
 msgid "length-difference"
 msgstr "longueur-difference"
 
-#: constraint.cpp:26
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr ""
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr ""
+
+#: constraint.cpp:30
 msgctxt "constr-name"
 msgid "symmetric"
 msgstr "symétrique"
 
-#: constraint.cpp:27
+#: constraint.cpp:31
 msgctxt "constr-name"
 msgid "symmetric-h"
 msgstr "symétrique-h"
 
-#: constraint.cpp:28
+#: constraint.cpp:32
 msgctxt "constr-name"
 msgid "symmetric-v"
 msgstr "symétrique-v"
 
-#: constraint.cpp:29
+#: constraint.cpp:33
 msgctxt "constr-name"
 msgid "symmetric-line"
 msgstr "symétrique-ligne"
 
-#: constraint.cpp:30
+#: constraint.cpp:34
 msgctxt "constr-name"
 msgid "at-midpoint"
 msgstr "au-point-milieu"
 
-#: constraint.cpp:31
+#: constraint.cpp:35
 msgctxt "constr-name"
 msgid "horizontal"
 msgstr "horizontal"
 
-#: constraint.cpp:32
+#: constraint.cpp:36
 msgctxt "constr-name"
 msgid "vertical"
 msgstr "vertical"
 
-#: constraint.cpp:33
+#: constraint.cpp:37
 msgctxt "constr-name"
 msgid "diameter"
 msgstr "diamètre"
 
-#: constraint.cpp:34
+#: constraint.cpp:38
 msgctxt "constr-name"
 msgid "pt-on-circle"
 msgstr "pt-sur-cercle"
 
-#: constraint.cpp:35
+#: constraint.cpp:39
 msgctxt "constr-name"
 msgid "same-orientation"
 msgstr "même-orientation"
 
-#: constraint.cpp:36
+#: constraint.cpp:40
 msgctxt "constr-name"
 msgid "angle"
 msgstr "angle"
 
-#: constraint.cpp:37
+#: constraint.cpp:41
 msgctxt "constr-name"
 msgid "parallel"
 msgstr "parallèle"
 
-#: constraint.cpp:38
+#: constraint.cpp:42
 msgctxt "constr-name"
 msgid "arc-line-tangent"
 msgstr "arc-ligne-tangente"
 
-#: constraint.cpp:39
+#: constraint.cpp:43
 msgctxt "constr-name"
 msgid "cubic-line-tangent"
 msgstr "cubique-ligne-tangente"
 
-#: constraint.cpp:40
+#: constraint.cpp:44
 msgctxt "constr-name"
 msgid "curve-curve-tangent"
 msgstr "courbe-courbe-tangente"
 
-#: constraint.cpp:41
+#: constraint.cpp:45
 msgctxt "constr-name"
 msgid "perpendicular"
 msgstr "perpendiculaire"
 
-#: constraint.cpp:42
+#: constraint.cpp:46
 msgctxt "constr-name"
 msgid "eq-radius"
 msgstr "eg-rayon"
 
-#: constraint.cpp:43
+#: constraint.cpp:47
 msgctxt "constr-name"
 msgid "eq-angle"
 msgstr "eg-angle"
 
-#: constraint.cpp:44
+#: constraint.cpp:48
 msgctxt "constr-name"
 msgid "eq-line-len-arc-len"
 msgstr "eg-ligne-long-arc-long"
 
-#: constraint.cpp:45
+#: constraint.cpp:49
 msgctxt "constr-name"
 msgid "lock-where-dragged"
 msgstr "verrouillé-où-déplacé"
 
-#: constraint.cpp:46
+#: constraint.cpp:50
 msgctxt "constr-name"
 msgid "comment"
 msgstr "commentaire"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
@@ -286,7 +306,7 @@ msgstr ""
 "Contraignez-les avec \"Contrainte -> Sur point avant de contraindre la "
 "tangente\"."
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
@@ -295,7 +315,7 @@ msgstr ""
 "Contraignez-les avec \"Contrainte -> Sur point avant de contraindre la "
 "tangente\"."
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
@@ -303,7 +323,7 @@ msgstr ""
 "Les courbes doivent partager un point final. Contraignez-les avec "
 "\"Contrainte -> Sur point avant de contraindre la tangente\"."
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -327,7 +347,7 @@ msgstr ""
 "    * Une face plane et un point (distance minimale)\n"
 "    * Un cercle ou un arc (diamètre)\n"
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -347,7 +367,7 @@ msgstr ""
 "    * Un point et un cercle ou un arc (point sur courbe)\n"
 "    * Un point et une face plane (point sur une face)\n"
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -378,30 +398,26 @@ msgstr ""
 "    * Un segment de ligne et un arc (la longueur de segment de ligne est "
 "égale à la longueur d'arc)\n"
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"Mauvaise sélection pour la contrainte du rapport de longueur. Cette "
-"contrainte peut s'appliquer à:\n"
-"\n"
-"    * Deux segments de ligne\n"
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"Mauvaise sélection pour la contrainte de différence de longueur. Cette "
-"contrainte peut s'appliquer à:\n"
-"\n"
-"    * Deux segments de ligne\n"
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -414,7 +430,7 @@ msgstr ""
 "    * Un segment de ligne et un point (point au milieu)\n"
 "    * Un segment de ligne et un plan de travail (point médian dans le plan)\n"
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -435,7 +451,7 @@ msgstr ""
 "    * Plan de travail, et deux points ou un segment de ligne (symétrique au "
 "plan de travail)\n"
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
@@ -443,7 +459,7 @@ msgstr ""
 "Un plan de travail doit être actif lors d'une contrainte de symétrie sans "
 "plan de symétrie explicite."
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
@@ -451,7 +467,7 @@ msgstr ""
 "Activez un plan de travail (avec Dessin -> Dans plan de travail) avant "
 "d'appliquer une contrainte horizontale ou verticale."
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -465,7 +481,7 @@ msgstr ""
 "    * deux points\n"
 "    * Un segment de ligne\n"
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
@@ -477,15 +493,15 @@ msgstr ""
 "\n"
 "    * Deux normales\n"
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr "Vous devez sélectionner une contrainte d'angle."
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr "Vous devez sélectionner une contrainte avec une étiquette associée."
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -500,11 +516,11 @@ msgstr ""
 "    * Un segment de ligne et une normale\n"
 "    * Deux normales\n"
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr "Courbe-Courbe tangence doit s'appliquer dans le plan de travail."
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -523,7 +539,7 @@ msgstr ""
 "    * Deux segments de ligne, des arcs ou des Béziers, qui partagent un "
 "point final (tangent)\n"
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -538,7 +554,7 @@ msgstr ""
 "    * Un segment de ligne et une normale\n"
 "    * Deux normales\n"
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
@@ -550,7 +566,11 @@ msgstr ""
 "\n"
 "    * un point\n"
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "NOUVEAU COMMENTAIRE - DOUBLE-CLIQUE POUR EDITER"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr "cliquez le centre du texte de commentaire"
 
@@ -580,26 +600,26 @@ msgstr ""
 "    * Un point et deux segments de ligne (plan au-travers d'un point et "
 "parallèle aux lignes)\n"
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
 msgstr "Le maillage du groupe actif est vide; Rien à exporter."
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr "les lignes à main levée ont été remplacées par des lignes continues"
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr "les lignes en zigzag ont été remplacées par des lignes continues"
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
 "Certains aspects du dessin n'ont pas d'équivalent DXF et n'ont pas été "
 "exportés:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
@@ -616,7 +636,11 @@ msgctxt "group-name"
 msgid "#references"
 msgstr "#références"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr ""
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
@@ -624,18 +648,18 @@ msgstr ""
 "Données non reconnues dans le fichier. Ce fichier peut être corrompu ou "
 "depuis une version plus récente du programme."
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr "Fichier manquant"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
 msgstr ""
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -644,17 +668,17 @@ msgid ""
 "permanently removed."
 msgstr ""
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr ""
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr ""
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr ""
@@ -828,295 +852,307 @@ msgid "Use &Perspective Projection"
 msgstr "Utiliser la vue en &Perspective"
 
 #: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr ""
+
+#: graphicswin.cpp:98
 msgid "Dimension &Units"
 msgstr "&Unités de dimensions"
 
-#: graphicswin.cpp:98
+#: graphicswin.cpp:99
 msgid "Dimensions in &Millimeters"
 msgstr "Dimensions en &Millimètres"
 
-#: graphicswin.cpp:99
+#: graphicswin.cpp:100
 msgid "Dimensions in M&eters"
 msgstr "Dimensions en &Mètres"
 
-#: graphicswin.cpp:100
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr "Dimensions en &Pouces"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr ""
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "Affichage &Barre d'outils"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "Affichage du &Navigateur de Propriété"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "&Plein Ecran"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "&Nouveau Groupe"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr "Dessin en &3d"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr "Dessin dans un nouveau &Plan de travail"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "Espacement &Linéaire"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "Espacement &Circulaire"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "E&xtruder"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
 msgstr "&Helix"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "&Lathe"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
 msgstr "Ré&volution"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
 msgstr "Lié / Assembler..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr "Lié Récent"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "&Dessin"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr "Dans le &Plan de travail"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr "N'importe où dans la &3d"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "&Point"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "&Plan de travail"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "Ligne - &Polyligne"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "Ligne de C&onstruction"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "&Rectangle"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "&Cercle"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "&Arc de Cercle"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "Spline Cubique de &Beziers"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr "&Texte en Police TrueType"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr "&Image"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "&Basculer en mode \"Construction\""
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "&Arc Tangent au Point"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "Diviser les Courbes à l'&Intersection"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "&Constraintes"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "&Distance / Diamètre"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "Dimension Maîtresse / Indicative"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "A&ngle"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "An&gle Maître / Indicatif"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "Autre angle S&upplémentaire"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "Basculer cote Maîtresse / cote Indicative"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "&Horizontal"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "&Vertical"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "&Sur Point / Courbe / Plan"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "&Egale Longueur / Rayon / Angle"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "R&apport de Longueur"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr ""
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "D&ifférence de Longueur"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr ""
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "Au &Milieu"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "&Symétrique"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "Para&llèle / Tangent"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "&Perpendiculaire"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "Même Orient&ation"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "Accrocher le point à l'&Emplacement"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "Commentaire"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "&Analyse"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "Mesure &Volume"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "Mesure &Aire"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "Mesure &Périmètre"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "Montrer les Pièces &Interférentes"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "Montrer les Arêtes &Nues"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
 msgstr "Montrer le &Centre de Gravité"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
 msgstr "Montrer les &sous-contraintes Points"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "&Tracer Point"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr "&Arrêt Tracé..."
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "Espacement &Dimension..."
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "&Aide"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "&Langue"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "&Site web / Manuel"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "&A propos"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr "(pas de fichier récent)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
 msgstr ""
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr "Pas de plan de travail actif, donc la grille ne va pas apparaître."
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -1130,19 +1166,19 @@ msgstr ""
 "Pour une projection en perspective, modifiez le facteur de perspective dans "
 "l'écran de configuration. Une valeur d'environ 0,3 est typique."
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr ""
 "Sélectionnez un point. Ce point deviendra le centre de la vue à l'écran."
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr ""
 "Aucune entité supplémentaire ne partage des points d'extrémité avec les "
 "entités sélectionnées."
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
@@ -1150,7 +1186,7 @@ msgstr ""
 "Pour utiliser cette commande, sélectionnez un point ou une autre entité à "
 "partir d'une pièce liée ou créez un groupe de liens dans le groupe actif."
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
@@ -1158,7 +1194,7 @@ msgstr ""
 "Aucun plan de travail n'est actif. Activez un plan de travail (avec Dessin -"
 "> Dans plan de travail) pour définir le plan pour la grille d'accrochage."
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
@@ -1167,13 +1203,13 @@ msgstr ""
 "des textes de commentaires ou des contraintes avec une étiquette. Pour "
 "accrocher une ligne, sélectionnez ses points d'extrémité."
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 "Aucun plan de travail sélectionné. Activation du plan de travail par défaut "
 "pour ce groupe."
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
@@ -1183,7 +1219,7 @@ msgstr ""
 "de travail par défaut. Essayez de sélectionner un plan de travail ou "
 "d'activer un groupe de \"Dessin dans nouveau plan travail\"."
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
@@ -1191,49 +1227,49 @@ msgstr ""
 "Mauvaise sélection pour l'arc tangent au point. Sélectionnez un seul point, "
 "ou ne sélectionnez rien pour configurer les paramètres de l'arc."
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr ""
 "cliquez un point sur l'arc (dessine dans le sens inverse des aiguilles d'une "
 "montre)"
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr "cliquez pour placer un point"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr "cliquez le premier point du segment de ligne"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr "cliquez le premier point de la ligne de construction"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr "cliquez le premier point du segment cubique"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr "cliquez pour placer le centre du cercle"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr "cliquez pour placer l'origine du plan de travail"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr "cliquez un coin du rectangle"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr "cliquez le haut à gauche du texte"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr "cliquez le haut à gauche de l'image"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1246,24 +1282,18 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr "dessin-en-3d"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
-"Mauvaise sélection pour un nouveau dessin dans le plan de travail. Ce groupe "
-"peut être créé avec:\n"
-"\n"
-"    * Un point (par le point, orthogonal aux axes de coordonnées)\n"
-"    * Un point et deux segments de ligne (par le point, parallèle aux "
-"lignes)\n"
-"    * Un plan de travail (copie du plan de travail)\n"
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
@@ -1271,16 +1301,16 @@ msgstr ""
 "Activez un plan de travail (Dessin -> Dans plan de travail) avant "
 "l'extrusion. Le croquis sera extrudé normalement au plan de travail."
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr "extruder"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1295,16 +1325,16 @@ msgstr ""
 "parallèle à la ligne / point normal, par le point)\n"
 "    * Un segment de ligne (révolution sur le segment de ligne)\n"
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr "révolution"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1313,16 +1343,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
 msgstr ""
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1331,12 +1361,12 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
 msgstr ""
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1353,41 +1383,45 @@ msgstr ""
 "    * Un point et une ligne ou une normale (tourner autour d'un axe par le "
 "point et parallèle à la ligne / normale)\n"
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr "rotation"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr "translation"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr "(sans nom)"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
 msgstr "contour non fermé ou tout n'est pas du même style!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr "les points ne sont pas tous coplanaires!"
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr "le contour s'entrecroise!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr "arête de longueur nulle!"
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr ""
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr "Vous devez dessiner dans un plan pour créer un arc tangent."
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
@@ -1395,7 +1429,7 @@ msgstr ""
 "Pour créer un arc tangent, sélectionnez un point où deux lignes (pas de "
 "construction) ou cercles de ce groupe et de ce plan se joignent."
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
@@ -1403,123 +1437,123 @@ msgstr ""
 "Impossible d'arrondir ce coin. Essayez un rayon plus petit, ou essayez de "
 "créer la géométrie souhaitée à la main avec des contraintes tangentielles."
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 "Impossible de diviser cette entité; Lignes, cercles ou cubiques uniquement."
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr "Vous devez dessiner dans un plan de travail pour diviser."
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
 msgstr ""
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr "Impossible de diviser; pas d'intersection trouvée."
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "Appliquer au style"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "Pas de style"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "Style personnalisé nouvellement créé ..."
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "Info Groupe"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "Info Style"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "Sélection Chaîne d'arêtes"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "Basculer cote maîtresse / cote indicative"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "Autre angle supplémentaire"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "Accrocher à la grille"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "Effacer le point de la Spline"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "Ajouter un point à la Spline"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr ""
 "Impossible d'ajouter le point spline: nombre maximum de points atteints."
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "Basculer en mode \"construction\"."
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "Effacer la contraint Point-Coïncident"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "Couper"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "Copier"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "Sélectionner tout"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "Coller"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "Coller transformé..."
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "Effacer"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "Désélectionner tout"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "Désélectionner survolé"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "Zoom pour ajuster"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr "cliquez pou le prochain point de ligne or appuyez sur Esc"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1527,15 +1561,15 @@ msgstr ""
 "Impossible de dessiner un rectangle en 3d; D'abord, activez un plan de "
 "travail avec \"Dessin -> Dans plan de travail\"."
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr "cliquez pour placer un autre coin de rectangle"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr "cliquez pour ajuster le rayon"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1543,22 +1577,22 @@ msgstr ""
 "Ne peut pas dessiner l'arc en 3d; D'abord, activez un plan de travail avec "
 "\"Dessin -> Dans plan de travail\"."
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr "cliquez pour placer un point"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr "cliquez le prochain point cubique ou appuyez sur Esc"
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 "Vous dessinez déjà dans un plan de travail; Sélectionner \"Dessiner en 3d\" "
 "avant de créer un nouveau plan de travail."
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1566,11 +1600,11 @@ msgstr ""
 "Impossible de dessiner du texte en 3d; D'abord, activer un plan de travail "
 "avec \"Dessin -> Dans plan de travail\"."
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
 msgstr ""
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
@@ -1578,219 +1612,225 @@ msgstr ""
 "Impossible de dessiner l'image en 3d; D'abord, activez un plan de travail "
 "avec \"Dessin -> Dans plan de travail\"."
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr "NOUVEAU COMMENTAIRE - DOUBLE-CLIQUE POUR EDITER"
-
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
 msgstr ""
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr ""
+
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
 msgstr ""
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr ""
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr ""
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr ""
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr ""
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
 msgstr ""
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr ""
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
 msgstr ""
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr ""
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr ""
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr ""
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr ""
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr ""
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr ""
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr ""
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr ""
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr ""
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr "sans nom"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr "Sauver fichier"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr "Ouvrir Fichier"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr "_Annuler"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr "_Sauver"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
 msgstr ""
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr "Sauvegarde automatique existante"
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
 msgstr ""
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
 msgstr ""
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
 msgstr ""
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
 msgstr ""
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr "Fichier modifié"
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
 msgstr ""
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
 msgstr ""
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
 msgstr ""
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
 msgstr ""
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
 msgstr ""
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr "(nouveau dessin)"
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr "Navigateur de propriété"
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
 "the text window."
 msgstr ""
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
 "dwg."
 msgstr ""
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
 msgstr ""
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr ""
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr ""
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
@@ -1798,7 +1838,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1807,7 +1847,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1815,7 +1855,7 @@ msgid ""
 "This introduces error, typically of around 1%."
 msgstr ""
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1826,13 +1866,13 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
 msgstr ""
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1843,7 +1883,7 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1854,36 +1894,36 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr ""
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
 msgstr ""
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
 msgstr ""
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1891,7 +1931,7 @@ msgid ""
 "The model contains %d triangles, from %d surfaces."
 msgstr ""
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1901,7 +1941,7 @@ msgid ""
 "Zero problematic edges, good.%s"
 msgstr ""
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1911,7 +1951,7 @@ msgid ""
 "%d problematic edges, bad.%s"
 msgstr ""
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1928,7 +1968,7 @@ msgid ""
 "© 2008-%d Jonathan Westhues and other authors.\n"
 msgstr ""
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
@@ -1936,27 +1976,27 @@ msgstr ""
 "Impossible d'attribuer le style à une entité dérivée d'une autre entité; "
 "Essayez d'attribuer un style au parent de cette entité."
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
 msgstr "Le nom d'un style ne peut pas être vide"
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr "Je ne peux pas répéter moins de 1 fois."
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr "Je ne peux pas répéter plus de 999 fois."
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
 msgstr "Un nom de groupe ne peut pas être vide"
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr "L'opacité doit être entre 0 et 1."
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr "Le rayon ne peut pas être zéro ou négatif."
 
@@ -2112,14 +2152,58 @@ msgctxt "button"
 msgid "&OK"
 msgstr ""
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr "L'échelle ne peut pas être zéro ou négative."
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr "Mauvais format:  Spécifiez x, y, z"
 
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Mauvaise sélection pour la contrainte du rapport de longueur. Cette "
+#~ "contrainte peut s'appliquer à:\n"
+#~ "\n"
+#~ "    * Deux segments de ligne\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Mauvaise sélection pour la contrainte de différence de longueur. Cette "
+#~ "contrainte peut s'appliquer à:\n"
+#~ "\n"
+#~ "    * Deux segments de ligne\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "R&apport de Longueur"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "D&ifférence de Longueur"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Mauvaise sélection pour un nouveau dessin dans le plan de travail. Ce "
+#~ "groupe peut être créé avec:\n"
+#~ "\n"
+#~ "    * Un point (par le point, orthogonal aux axes de coordonnées)\n"
+#~ "    * Un point et deux segments de ligne (par le point, parallèle aux "
+#~ "lignes)\n"
+#~ "    * Un plan de travail (copie du plan de travail)\n"
+
 #~ msgid "Specify between 0 and 8 digits after the decimal."
 #~ msgstr "Spécifiez entre 0 et 8 chiffres après la virgule."
 
index 8cc4e6076d52a79ce78d8d5a14d0926462137176..bf9bbfbb15419dc818fcb799526d88989ab188f2 100644 (file)
@@ -2,22 +2,23 @@
 # Copyright (C) 2017 the SolveSpace authors
 # This file is distributed under the same license as the SolveSpace package.
 # EvilSpirit <evilspirit@evilspirit.org>, 2017.
+# Olesya Gerasimenko <translation-team@basealt.ru>, 2021.
 msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
-"PO-Revision-Date: 2017-04-21 10:29+0700\n"
-"Last-Translator: evilspirit@evilspirit.org\n"
-"Language-Team: EvilSpirit\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2021-10-04 15:33+0300\n"
+"Last-Translator: Olesya Gerasimenko <translation-team@basealt.ru>\n"
+"Language-Team: Basealt Translation Team\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=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.0.1\n"
+"X-Generator: Lokalize 21.08.1\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
@@ -27,50 +28,50 @@ msgstr ""
 "можно только находясь в рабочей плоскости.\n"
 "Активируйте рабочую плоскость через Эскиз->В Рабочей Плоскости"
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr "Буфер обмена пуст; нечего вставлять."
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr "Укажите в поле 'количество' хотя бы одну копию для вставки."
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr "Масштабный коэффициент не может быть нулевым."
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr "Выберите одну точку в качестве центра вращения."
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr "Выберите две точки, чтобы задать вектор смещения."
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
 msgstr ""
 "Трансформация не задана. Все копии будут расположены в одном и том же месте."
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr "Слишком много элементов для вставки; разбейте на несколько частей."
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr "Рабочая плоскость не активна"
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr "Неверный формат: введите координаты как x, y, z"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr "Неверный формат: введите цвет как r, g, b"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
@@ -78,25 +79,25 @@ msgstr ""
 "Коэффициент перспективы не будет иметь эффект, пока вы не включите Вид-"
 ">Перспективная Проекция."
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr "Введите число от 0 до %d."
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr "Масштабный коэффициент не может быть нулевым!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr "Радиус режущего инструмента не может быть отрицательным!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr ""
 "Неверное значение: интервал автосохранения должен быть положительным числом"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr ""
 "Неверный формат: введите целое число, чтобы задать интервал автосохранения"
@@ -168,115 +169,135 @@ msgstr "отношение-длин"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr "отношение-длин-дуга-дуга"
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr "отношение-длин-дуга-отрезок"
+
+#: constraint.cpp:27
+msgctxt "constr-name"
 msgid "length-difference"
 msgstr "разность-длин"
 
-#: constraint.cpp:26
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr "разность-длин-дуга-дуга"
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr "разность-длин-дуга-отрезок"
+
+#: constraint.cpp:30
 msgctxt "constr-name"
 msgid "symmetric"
 msgstr "симметричность"
 
-#: constraint.cpp:27
+#: constraint.cpp:31
 msgctxt "constr-name"
 msgid "symmetric-h"
 msgstr "симметричность-гориз"
 
-#: constraint.cpp:28
+#: constraint.cpp:32
 msgctxt "constr-name"
 msgid "symmetric-v"
 msgstr "симметричность-верт"
 
-#: constraint.cpp:29
+#: constraint.cpp:33
 msgctxt "constr-name"
 msgid "symmetric-line"
 msgstr "симметричность-по-оси"
 
-#: constraint.cpp:30
+#: constraint.cpp:34
 msgctxt "constr-name"
 msgid "at-midpoint"
 msgstr "на-середине"
 
-#: constraint.cpp:31
+#: constraint.cpp:35
 msgctxt "constr-name"
 msgid "horizontal"
 msgstr "горизонтальность"
 
-#: constraint.cpp:32
+#: constraint.cpp:36
 msgctxt "constr-name"
 msgid "vertical"
 msgstr "вертикальность"
 
-#: constraint.cpp:33
+#: constraint.cpp:37
 msgctxt "constr-name"
 msgid "diameter"
 msgstr "диаметр"
 
-#: constraint.cpp:34
+#: constraint.cpp:38
 msgctxt "constr-name"
 msgid "pt-on-circle"
 msgstr "тчк-на-окружности"
 
-#: constraint.cpp:35
+#: constraint.cpp:39
 msgctxt "constr-name"
 msgid "same-orientation"
 msgstr "идентичная-ориентация"
 
-#: constraint.cpp:36
+#: constraint.cpp:40
 msgctxt "constr-name"
 msgid "angle"
 msgstr "угол"
 
-#: constraint.cpp:37
+#: constraint.cpp:41
 msgctxt "constr-name"
 msgid "parallel"
 msgstr "параллельность"
 
-#: constraint.cpp:38
+#: constraint.cpp:42
 msgctxt "constr-name"
 msgid "arc-line-tangent"
 msgstr "кас-дуга-линия"
 
-#: constraint.cpp:39
+#: constraint.cpp:43
 msgctxt "constr-name"
 msgid "cubic-line-tangent"
 msgstr "кас-сплайн-линия"
 
-#: constraint.cpp:40
+#: constraint.cpp:44
 msgctxt "constr-name"
 msgid "curve-curve-tangent"
 msgstr "кас-кривых"
 
-#: constraint.cpp:41
+#: constraint.cpp:45
 msgctxt "constr-name"
 msgid "perpendicular"
 msgstr "перпендикулярность"
 
-#: constraint.cpp:42
+#: constraint.cpp:46
 msgctxt "constr-name"
 msgid "eq-radius"
 msgstr "равенство-радиусов"
 
-#: constraint.cpp:43
+#: constraint.cpp:47
 msgctxt "constr-name"
 msgid "eq-angle"
 msgstr "равенство-углов"
 
-#: constraint.cpp:44
+#: constraint.cpp:48
 msgctxt "constr-name"
 msgid "eq-line-len-arc-len"
 msgstr "равен-длины-линии-длины-дуги"
 
-#: constraint.cpp:45
+#: constraint.cpp:49
 msgctxt "constr-name"
 msgid "lock-where-dragged"
 msgstr "фиксация"
 
-#: constraint.cpp:46
+#: constraint.cpp:50
 msgctxt "constr-name"
 msgid "comment"
 msgstr "комментарий"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
@@ -285,7 +306,7 @@ msgstr ""
 "'Ограничения -> Точка на Примитиве' перед тем, как применять ограничение "
 "касательности."
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
@@ -294,7 +315,7 @@ msgstr ""
 "'Ограничения -> Точка на Примитиве' перед тем, как применять ограничение "
 "касательности."
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
@@ -303,7 +324,7 @@ msgstr ""
 "'Ограничения -> Точка на Примитиве' перед тем, как применять ограничение "
 "касательности."
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -328,7 +349,7 @@ msgstr ""
 "    * грань и точку (расстояние от точки до плоскости грани)\n"
 "    * окружность или дугу (диаметр / радиус)\n"
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -348,7 +369,7 @@ msgstr ""
 "    * точку и окружность / дугу / сплайн (точка на кривой)\n"
 "    * точку и грань (точка на грани)\n"
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -376,30 +397,38 @@ msgstr ""
 "    * две окружности / дуги (равенство радиусов)\n"
 "    * отрезок и дугу (равенство длины отрезка и длины дуги)\n"
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"Неправильное выделение для ограничения 'отношение длин'.\n"
-"Ð\9eгÑ\80аниÑ\87ение Ð¼Ð¾Ð¶ÐµÑ\82 Ð¿Ñ\80инимаÑ\82Ñ\8c Ð² ÐºÐ°Ñ\87еÑ\81Ñ\82ве Ð²Ñ\8bделениÑ\8f Ñ\81ледÑ\83Ñ\8eÑ\89ие Ð¿Ñ\80имиÑ\82ивÑ\8b:\n"
+"Неправильное выделение для ограничения 'отношение длин'. Ограничение может "
+"принимать в качестве выделения следующие примитивы:\n"
 "\n"
 "    * два отрезка\n"
+"    * две дуги\n"
+"    * дугу и отрезок\n"
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"Ð\9dепÑ\80авилÑ\8cное Ð²Ñ\8bделение Ð´Ð»Ñ\8f Ð¾Ð³Ñ\80аниÑ\87ениÑ\8f 'Ñ\80азниÑ\86а Ð´Ð»Ð¸Ð½'.\n"
-"Ð\9eгÑ\80аниÑ\87ение Ð¼Ð¾Ð¶ÐµÑ\82 Ð¿Ñ\80инимаÑ\82Ñ\8c Ð² ÐºÐ°Ñ\87еÑ\81Ñ\82ве Ð²Ñ\8bделениÑ\8f Ñ\81ледÑ\83Ñ\8eÑ\89ие Ð¿Ñ\80имиÑ\82ивÑ\8b:\n"
+"Ð\9dепÑ\80авилÑ\8cное Ð²Ñ\8bделение Ð´Ð»Ñ\8f Ð¾Ð³Ñ\80аниÑ\87ениÑ\8f 'Ñ\80азноÑ\81Ñ\82Ñ\8c Ð´Ð»Ð¸Ð½'. Ð\9eгÑ\80аниÑ\87ение Ð¼Ð¾Ð¶ÐµÑ\82 "
+"принимать в качестве выделения следующие примитивы:\n"
 "\n"
 "    * два отрезка\n"
+"    * две дуги\n"
+"    * дугу и отрезок\n"
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -412,7 +441,7 @@ msgstr ""
 "    * точку и отрезок (точка на середине отрезка)\n"
 "    * отрезок и рабочую плоскость (середина отрезка на плоскости)\n"
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -432,7 +461,7 @@ msgstr ""
 "    * рабочую плоскость и две точки / отрезок (симметричность относительно "
 "рабочей плоскости\n"
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
@@ -440,7 +469,7 @@ msgstr ""
 "Рабочая плоскость должна быть активна для того, чтобы создать\n"
 "ограничение симметричности без явного указания плоскости симметрии."
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
@@ -448,7 +477,7 @@ msgstr ""
 "Рабочая плоскость должна быть активирована (Эскиз -> В рабочей плоскости)\n"
 "перед тем, как накладывать ограничения горизонтальности / вертикальности."
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -462,30 +491,30 @@ msgstr ""
 "    * две точки\n"
 "    * отрезок\n"
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two normals\n"
 msgstr ""
-"Неправильное выделение для ограничения \"идентичная ориентация\".\n"
+"Неправильное выделение для ограничения 'идентичная ориентация'.\n"
 "Ограничение может принимать в качестве выделения следующие примитивы:\n"
 "\n"
 "    * два координатных базиса('нормали')\n"
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr ""
 "Переключатся между смежными углами можно только выбрав ограничение угла."
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr ""
 "Переключать режим 'размера для справок' возможно только для ограничений, "
 "имеющих размерное значение."
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -500,12 +529,12 @@ msgstr ""
 "    * отрезок и координатный базис (нормаль)\n"
 "    * два координатных базиса (нормали)\n"
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr ""
 "Ограничение касательности может быть наложено только в рабочей плоскости."
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -524,7 +553,7 @@ msgstr ""
 "    * два отрезка, две дуги или два сплайна, соединенных крайними точками "
 "(касательность)\n"
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -539,19 +568,23 @@ msgstr ""
 "    * отрезок и координатный базис (нормаль)\n"
 "    * два координатных базиса (нормали)\n"
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
 "\n"
 "    * a point\n"
 msgstr ""
-"Неправильное выделение для ограничения 'Фиксация'.\n"
+"Неправильное выделение для ограничения 'фиксация'.\n"
 "Ограничение может принимать в качестве выделения следующие примитивы:\n"
 "\n"
 "    * точку\n"
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "КОММЕНТАРИЙ -- ДВОЙНОЙ ЩЕЛЧОК ДЛЯ РЕДАКТИРОВАНИЯ"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr "кликните мышью там, где будет расположен текстовый комментарий"
 
@@ -560,6 +593,7 @@ msgid ""
 "No solid model present; draw one with extrudes and revolves, or use Export "
 "2d View to export bare lines and curves."
 msgstr ""
+"Тела не найдены; создайте их или используйте экспорт двумерных объектов."
 
 #: export.cpp:61
 msgid ""
@@ -570,27 +604,34 @@ msgid ""
 "    * a point and two line segments (plane through point and parallel to "
 "lines)\n"
 msgstr ""
+"Неправильное выделение для экспорта сечения. Необходимо выделить:\n"
+"\n"
+"    * Ничего, но с активированной рабочей плоскостью (рабочая плоскость "
+"будет плоскостью сечения)\n"
+"    * грань (сечение через грань)\n"
+"    * точку и два отрезка (сечение плоскостью, заданной двумя отрезками, "
+"построенной через указанную точку)\n"
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
-msgstr ""
+msgstr "Активная группа не содержит тел; нечего экспортировать."
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr "Стили линии 'от руки' были заменены сплошными линиями"
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr "Стили линии 'зиг-заг' были заменены сплошными линиями"
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
 "Некоторые элементы чертежа не имеют аналогов в DXF-представлении и не были "
 "экспортированы:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
@@ -607,7 +648,11 @@ msgctxt "group-name"
 msgid "#references"
 msgstr "система-координат"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "Файл пуст. Возможно он поврежден."
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
@@ -615,18 +660,18 @@ msgstr ""
 "Некоторые данные из этого файла не распознаны. Возможно, файл поврежден или "
 "создан в более новой версии программы"
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr "Файл Отсутствует"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
-msgstr ""
+msgstr "Связанный файл “%s” отсутствует."
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -638,17 +683,17 @@ msgstr ""
 "Если вы ответите \"Нет\", то вся геометрия, которая зависит от "
 "отсутствующего файла будет удалена."
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr "Да"
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr "Нет"
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr "Отменить"
@@ -767,15 +812,15 @@ msgstr "С&бросить Выделение"
 
 #: graphicswin.cpp:78
 msgid "&Line Styles..."
-msgstr ""
+msgstr "Стили Линий..."
 
 #: graphicswin.cpp:79
 msgid "&View Projection..."
-msgstr "&View Прое&кция..."
+msgstr "&Проекция вида..."
 
 #: graphicswin.cpp:81
 msgid "Con&figuration..."
-msgstr ""
+msgstr "Настройки..."
 
 #: graphicswin.cpp:84
 msgid "&View"
@@ -815,302 +860,314 @@ msgstr "Показать &Сетку"
 
 #: graphicswin.cpp:95
 msgid "Darken Inactive Solids"
-msgstr ""
+msgstr "Затемнять Неактивные Тела"
 
 #: graphicswin.cpp:96
 msgid "Use &Perspective Projection"
 msgstr "Перспективная Прое&кция"
 
 #: graphicswin.cpp:97
-msgid "Dimension &Units"
-msgstr ""
+msgid "Show E&xploded View"
+msgstr "Показать &Развернутый Вид"
 
 #: graphicswin.cpp:98
+msgid "Dimension &Units"
+msgstr "Единицы Измерения"
+
+#: graphicswin.cpp:99
 msgid "Dimensions in &Millimeters"
 msgstr "Размеры в Ми&ллиметрах"
 
-#: graphicswin.cpp:99
+#: graphicswin.cpp:100
 msgid "Dimensions in M&eters"
-msgstr ""
+msgstr "Размеры в Метрах"
 
-#: graphicswin.cpp:100
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr "Размеры в Дю&ймах"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr "Размеры в &Футах и дюймах"
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "Показывать Па&нель Инструментов"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "Показывать Брау&зер"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "Полно&экранный Режим"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "&Группа"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr "Создать Эскиз в &3d"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr "Создать Эскиз в Новой &Рабочей Плоскости"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "&Линейный Массив"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "&Круговой Массив"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "Тело &Выдавливания"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
-msgstr ""
+msgstr "Тело Винтовое"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "Тело В&ращения"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
-msgstr ""
+msgstr "Тело В&ращения"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
 msgstr "&Импорт Детали / Сборка..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr "Последние &Детали"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "&Эскиз"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr "В &Рабочей Плоскости"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr "Режим &3d"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "Опорная &Точка"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "Рабочая &Плоскость"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "&Отрезок"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "&Вспомогательный Отрезок"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "Прямоу&гольник"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "О&кружность"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "Д&уга Окружности"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "Кубический &Сплайн Безье"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr "Т&екст TrueType"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr "И&зображение"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "Переключить Режим Вс&помогательных Построений"
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "Кас&ательная в Точке"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "Ра&збить Кривые Пересечением"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "&Ограничения"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "&Расстояние / Диаметр"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "&Справочный Размер"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "&Угол"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "С&правочный Угол"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "Переключить Сме&жный Угол"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "Переключить Режим Размера Для Спра&вок"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "&Горизонтальность"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "&Вертикальность"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "&Точка на Примитиве"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "&Равенство Длин / Радиусов / Углов"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "Отно&шение Длин"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr "&Отношение длин (дуга)"
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "Ра&зница Длин"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr "Р&азность длин (дуга)"
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "&На Середине"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "С&имметричность"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "Пара&ллельность / Касательность"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "Перпендикул&ярность"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "Идентичная &Ориентация"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "За&фиксировать"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "Текстовый &Комментарий"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "&Анализ"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "Измерить &Объем"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "Измерить П&лощадь"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "Измерить П&ериметр"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "Показать Пе&ресекающиеся Детали"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "Показать Про&блемные Ребра"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
-msgstr ""
+msgstr "Показать Центр Масс"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
-msgstr ""
+msgstr "Показать Свободные Точки"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "Включить &Трассировку Точки"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr "Остановить Тра&ссировку..."
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "Плавное Из&менение Размера..."
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "&Помощь"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "&Язык"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "Вебсайт / &Справка"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "О &Программе"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr "(пусто)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
-msgstr ""
+msgstr "Файл '%s' не существует."
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr "Сетку не будет видно, пока рабочая плоскость не активирована."
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -1124,25 +1181,25 @@ msgstr ""
 "перспективы на конфигурационной странице браузера.\n"
 "Значение по умолчанию 0.3."
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr "Выделите точку. Вид будет отцентрован по этой точке."
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr "Нет дополнительных объектов, соединенных с выбранными примитивами."
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
 msgstr ""
 "Чтобы использовать эту команду, выделите точку или другой примитив, "
-"принадлежащий импортированной детали или активируйте группу импортированной "
+"принадлежащий импортированной детали, или активируйте группу импортированной "
 "детали."
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
@@ -1150,7 +1207,7 @@ msgstr ""
 "Рабочая плоскость не активна. Активируйте ее через Эскиз -> В Рабочей "
 "Плоскости чтобы определить плоскость для сетки."
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
@@ -1159,13 +1216,13 @@ msgstr ""
 "текстовые комментарии или ограничения с размерными значениями. Чтобы "
 "привязать отрезок или другой примитив, выбирайте его точки."
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 "Рабочая плоскость не активна. Активирована рабочая плоскость по умолчанию "
 "для данной группы."
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
@@ -1175,7 +1232,7 @@ msgstr ""
 "по умолчанию. Попробуйте выделить рабочую плоскость или создать новую с "
 "помощью Группа -> Создать Эскиз в Новой Рабочей Плоскости."
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
@@ -1184,53 +1241,54 @@ msgstr ""
 "точку, либо запустите команду без выделения, чтобы перейти к окну настроек "
 "этой команды."
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr ""
 "кликните мышью там, где хотите создать дугу окружности (дуга будет "
 "нарисована против часовой стрелки)"
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr "кликните мышью там, где хотите создать опорную точку"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr "кликните мышью там, где хотите создать первую точку отрезка"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr ""
 "кликните мышью  там, где хотите создать первую точку вспомогательного отрезка"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr ""
 "кликните мышью там, где хотите создать первую точку кубического сплайна Безье"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr "кликните мышью там, где будет находиться центр окружности"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr ""
 "кликните мышью там, где будет находиться точка, через которую будет "
 "построена рабочая плоскость"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr "кликните мышью там, где будет находиться один из углов прямоугольника"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr "кликните мышью там, где хотите создать текст"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr ""
+"кликните мышью там, где будет расположен левый верхний угол изображения"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1243,26 +1301,25 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr "эскиз-в-3d"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
-"Неправильное выделение для создания эскиза.\n"
-"Группа может быть создана, используя в качестве выделения следующие "
-"примитивы:\n"
+"Неправильное выделение для создания эскиза в рабочей плоскости. Группа может "
+"быть создана, используя в качестве выделения следующие примитивы:\n"
 "\n"
-"    * точку (рабочая плоскость, ориентированная к ближайшему виду, "
-"проходящая через точку)\n"
-"    * точку и два отрезка (рабочая плоскость, проходящая через точку и "
-"параллельная отрезкам)\n"
-"    * рабочую плоскость (копия рабочей плоскости)\n"
+"    * точку (через точку, ортогонально осям координат)\n"
+"    * точку и два отрезка (через точку, параллельно отрезкам)\n"
+"    * точку и нормаль (через точку, ортогонально нормали)\n"
+"    * рабочую плоскость (копию рабочей плоскости)\n"
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
@@ -1270,16 +1327,18 @@ msgstr ""
 "Выберите рабочую плоскость (Эскиз -> В Рабочей Плоскости) перед созданием "
 "группы выдавливания. Эскиз будет выдавлен по нормали к рабочей плоскости."
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr "тело-выдавливания"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr ""
+"Операция создания тела вращения может быть применена только к плоским "
+"эскизам."
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1291,21 +1350,23 @@ msgstr ""
 "Группа может быть создана, используя в качестве выделения следующие "
 "примитивы:\n"
 "\n"
-"    * точку и отрезок / координатных базис (нормаль) (тело вращения вокруг "
+"    * точку и отрезок / координатный базис (нормаль) (тело вращения вокруг "
 "оси, проходящей через точку и параллельной отрезку / нормали)\n"
 "    * отрезок (тело вращения вокруг оси, проходящей через отрезок)\n"
 "\n"
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr "тело-вращения"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr ""
+"Операция создания тела вращения может быть применена только к плоским "
+"эскизам."
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1313,17 +1374,27 @@ msgid ""
 "to line / normal, through point)\n"
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
+"Неправильное выделение для создания группы тела вращения. \n"
+"Группа может быть создана, используя в качестве выделения следующие "
+"примитивы:\n"
+"\n"
+"    * точку и отрезок / координатный базис (нормаль) (тело вращения вокруг "
+"оси, проходящей через точку и параллельной отрезку / нормали)\n"
+"    * отрезок (тело вращения вокруг оси, проходящей через отрезок)\n"
+"\n"
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
-msgstr ""
+msgstr "тело-вращения"
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr ""
+"Операция создания винтового тела может быть применена только к плоским "
+"эскизам."
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1331,13 +1402,21 @@ msgid ""
 "to line / normal, through point)\n"
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
+"Неправильное выделение для создания винтового тела.\n"
+"Группа может быть создана, используя в качестве выделения следующие "
+"примитивы:\n"
+"\n"
+"    * точку и отрезок или координатный базис (нормаль) (вращение вокруг "
+"направления, параллельного линии / нормали, построенное через выбранную "
+"точку)\n"
+"    * отрезок (вращение вокруг отрезка)\n"
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
-msgstr ""
+msgstr "тело-винтовое"
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1352,47 +1431,51 @@ msgstr ""
 "\n"
 "    * точку при активной рабочей плоскости (вращение в плоскости вокруг "
 "выбранной точки)\n"
-"    * точку и отрезок / координатных базис (нормаль) (вращение вокруг оси, "
+"    * точку и отрезок / координатный базис (нормаль) (вращение вокруг оси, "
 "проходящей через точку и параллельной отрезку / нормали)\n"
 "\n"
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr "круговой-массив"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr "линейный-массив"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr "(без имени)"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
 msgstr "незамкнутый контур или несовпадение стилей!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr "не все точки лежат в одной плоскости!"
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr "контур имеет самопересечения!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr "вырожденный отрезок!"
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr ""
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr ""
 "Скругления эскиза можно создавать только когда рабочая плоскость "
 "активирована."
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
@@ -1400,7 +1483,7 @@ msgstr ""
 "Чтобы создать скругление эскиза, выберите точку, где соединяются два "
 "примитива, не принадлежащих к вспомогательной геометрии."
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
@@ -1408,400 +1491,418 @@ msgstr ""
 "Невозможно скруглить угол. Попробуйте радиус поменьше или создайте требуемую "
 "геометрию с помощью Ограничения -> Параллельность / Касательность."
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 "Невозможно разделить такие примитивы. Выберите линии, окружности или "
 "кубические сплайны."
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr ""
 "Пересечение примитивов работает только когда рабочая плоскость активна."
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
 msgstr ""
+"Выберите два пересекающихся примитива (два отрезка/окружности/дуги или "
+"отрезок/окружность/дугу и точку)"
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr "Невозможно разделить пересекаемые примитивы: пересечений нет."
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "Применить Стиль"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "Стиль по Умолчанию"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "Создать Новый Стиль..."
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "Настройки Группы"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "Настройки Стиля"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "Выделить Последовательность Примитивов"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "Переключить Режим Размера Для Справок"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "Переключить Смежный Угол"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "Привязать к Сетке"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "Удалить Точку Сплайна"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "Добавить Точку Сплайна"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr ""
 "Невозможно добавить точку сплайна: достигнуто ограничение максимального "
 "количества точек для сплайна."
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "Переключить Режим 'Дополнительные Построения'."
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "Удалить Ограничение Совпадения Точек"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "Вырезать"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "Копировать"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "Выделить Все"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "Вставить"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "Вставить с Трансформацией..."
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "Удалить"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "Сбросить Выделение"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "Снять Выделение с Выбранного"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "Показать Все"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr "кликните мышью там, где хотите расположить следующую точку"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr ""
 "Невозможно начертить прямоугольник, когда рабочая плоскость не активна."
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr "кликните мышью там, где хотите расположить другой угол прямоугольника"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr "кликните, чтобы задать радиус"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "Невозможно создать дугу, когда нет активной рабочей плоскости."
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr "кликните мышью там, где хотите создать точку"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr ""
 "кликните мышью там, где хотите создать следующую точку сплайна или нажмите "
 "Esc для завершения операции."
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 "Рабочая плоскость уже активна. Перейдите в режим 3d перед созданием новой "
 "рабочей плоскости."
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "Невозможно создать текст, когда нет активной рабочей плоскости."
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
-msgstr ""
+msgstr "кликните, чтобы расположить правый нижний угол текста"
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
-msgstr ""
-
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr "КОММЕНТАРИЙ -- ДВОЙНОЙ ЩЕЛЧОК ДЛЯ РЕДАКТИРОВАНИЯ"
+msgstr "Невозможно создать изображение. Активируйте рабочую плоскость."
 
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
 msgstr "проекты SolveSpace"
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr "ВСЕ"
+
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
-msgstr ""
+msgstr "IDF печатная плата"
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr "STL треугольная сетка"
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr "PNG изображение"
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr "STL полигональная сетка"
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr "Wavefront OBJ полигональная сетка"
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
-msgstr "Three.js-совместимая полигональная сетка с просмторщиком"
+msgstr "Three.js-совместимая полигональная сетка с просмотрщиком"
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr "Three.js-совместимая полигональная сетка"
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
-msgstr ""
+msgstr "VRML файл"
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr "STEP файл"
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr "PDF документ"
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr "Encapsulated PostScript"
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr "SVG изображение"
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr "DXF файл (AutoCAD 2007)"
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr "HPGL файл"
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr "G Code"
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr "AutoCAD DXF и DWG файлы"
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr "CSV файлы (значения, разделенные запятой)"
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr "без имени"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr "Сохранить Файл"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr "Открыть Файл"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr "Отменить"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr "Сохранить"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
-msgstr ""
+msgstr "_Открыть"
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr "Автосохранение Доступно"
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
-msgstr ""
+msgstr "Автоматически сохраненный файл доступен для данного проекта."
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
-msgstr ""
+msgstr "Хотите загрузить автосохраненный файл вместо исходного?"
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
-msgstr ""
+msgstr "&Загрузить Автосохранение"
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
-msgstr ""
+msgstr "&Не Загружать"
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr "Измененный Файл"
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
-msgstr ""
+msgstr "Сохранить изменения, сделанные в файле “%s”?"
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
-msgstr ""
+msgstr "Сохранить изменения, сделанные в новом проекте?"
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
-msgstr ""
+msgstr "Изменения будут утеряны, если их не сохранить."
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
-msgstr ""
+msgstr "&Сохранить"
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
-msgstr ""
+msgstr "&Не Сохранять"
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr "(новый проект)"
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr "Браузер"
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
 "the text window."
 msgstr ""
+"Ограничения отображаются, и будут экспортированы в файл. Предположительно, "
+"это не то, что требуется, если так, необходимо спрятать их, нажав ссылку "
+"вверху окна Браузера."
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
 "dwg."
 msgstr ""
+"Неподдерживаемый тип файла '%s'. Поддерживаются файлы с расширением .dxf и ."
+"dwg."
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
-msgstr ""
+msgstr "У ограничения должно быть значение и оно не должно быть справочным."
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr ""
+"Неправильное выделение для операции изменения значения с заданным шагом; "
+"необходимо выбрать ограничение со значением."
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
-msgstr ""
+msgstr "Сборка не содержит пересечения деталей - это хорошо."
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
 "\n"
 "    %s"
 msgstr ""
+"Объем тел:\n"
+"\n"
+"    %s"
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1809,16 +1910,24 @@ msgid ""
 "\n"
 "    %s"
 msgstr ""
+"\n"
+"Объем тел текущей группы:\n"
+"\n"
+"    %s"
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
 "Curved surfaces have been approximated as triangles.\n"
 "This introduces error, typically of around 1%."
 msgstr ""
+"\n"
+"\n"
+"Кривые аппроксимированы кусочно-линейными функциями.\n"
+"Это приводит к ошибке в расчетах, обычно в пределах 1%."
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1828,14 +1937,22 @@ msgid ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 msgstr ""
+"Площадь поверхности выбранных граней:\n"
+"\n"
+"    %s\n"
+"\n"
+"Кривые аппроксимированы кусочно-линейными функциями.\n"
+"Это приводит к ошибке в расчетах, обычно в пределах 1%%."
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
 msgstr ""
+"Эта группа не содержит замкнутых областей. В ней нет замкнутых контуров, "
+"примитивы не лежат в одной плоскости или самопересекаются."
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1845,8 +1962,14 @@ msgid ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 msgstr ""
+"Площадь замкнутой области текущей группы:\n"
+"\n"
+"    %s\n"
+"\n"
+"Кривые аппроксимированы кусочно-линейными функциями.\n"
+"Это приводит к ошибке в расчетах, обычно в пределах 1%%."
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1856,45 +1979,56 @@ msgid ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 msgstr ""
+"Длина выбранных примитивов:\n"
+"\n"
+"    %s\n"
+"\n"
+"Кривые аппроксимированы кусочно-линейными функциями.\n"
+"Это приводит к ошибке в расчетах, обычно в пределах 1%%."
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr ""
+"Неправильное выделение для расчета периметра; необходимо выбирать только "
+"отрезки, дуги и кривые в качестве исходных данных"
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
-msgstr ""
+msgstr "Неправильное выделение для трассировки; необходимо выбрать одну точку."
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
-msgstr ""
+msgstr "Невозможно записать в '%s'"
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
-msgstr ""
+msgstr "Полигональная сетка содержит самопересечения (это плохо)"
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
-msgstr ""
+msgstr "Полигональная сетка не содержит самопересечений (это хорошо)"
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
-msgstr ""
+msgstr "Полигональная сетка содержит \"оголенные\" ребра (это плохо)"
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
-msgstr ""
+msgstr "Полигональная сетка герметична (это хорошо)"
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
 "\n"
 "The model contains %d triangles, from %d surfaces."
 msgstr ""
+"\n"
+"\n"
+"Модель содержит %d треугольников, содержащихся в %d поверхностях."
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1903,8 +2037,13 @@ msgid ""
 "\n"
 "Zero problematic edges, good.%s"
 msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Нет проблемных ребер - это хорошо.%s"
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1913,8 +2052,13 @@ msgid ""
 "\n"
 "%d problematic edges, bad.%s"
 msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d найдены проблемные ребра - это плохо.%s"
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1930,8 +2074,22 @@ msgid ""
 "\n"
 "© 2008-%d Jonathan Westhues and other authors.\n"
 msgstr ""
+"Это SolveSpace версии %s.\n"
+"\n"
+"Для дополнительной информации посетите сайт: http://solvespace.com/\n"
+"\n"
+"SolveSpace - это свободное программное обеспечение: поощряется изменение, "
+"улучшение\n"
+"распространение программы по условиям лицензии GNU\n"
+"General Public License (GPL) версии 3 или новее.\n"
+"\n"
+"НИКАКИХ ГАРАНТИЙ за пределами прав, \n"
+"предусмотренных законом. Дополнительная информация на сайте: http://gnu.org/"
+"licenses/\n"
+"\n"
+"© 2008-%d Джонатан Вэстью и другие авторы.\n"
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
@@ -1939,27 +2097,27 @@ msgstr ""
 "Невозможно применить стиль к примитиву, который произошел от другого "
 "примитива. Попробуйте применить стиль к исходному примитиву."
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
 msgstr "Имя стиля не может быть пустым."
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr "Невозможно сделать повторение меньше, чем 1 раз."
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr "Невозможно сделать повтор больше, чем 999 раз."
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
 msgstr "Имя группы не может быть пустым."
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr "Прозрачность должна быть числом от нуля до единицы."
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr "Радиус не может быть нулевым или отрицательным."
 
@@ -1985,7 +2143,7 @@ msgstr "Начертить текст TrueType"
 
 #: toolbar.cpp:28
 msgid "Sketch image from a file"
-msgstr ""
+msgstr "Импортировать изображение из файла"
 
 #: toolbar.cpp:30
 msgid "Create tangent arc at selected point"
@@ -2065,11 +2223,11 @@ msgstr "Создать группу вращения текущего эскиз
 
 #: toolbar.cpp:72
 msgid "New group helix from active sketch"
-msgstr ""
+msgstr "Создать группу тела выдавливания по винтовой линии из текущего эскиза"
 
 #: toolbar.cpp:74
 msgid "New group revolve active sketch"
-msgstr ""
+msgstr "Создать группу тела вращения из текущего эскиза"
 
 #: toolbar.cpp:76
 msgid "New group step and repeat rotating"
@@ -2114,14 +2272,60 @@ msgctxt "button"
 msgid "&OK"
 msgstr "ХОРОШО"
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr "Масштабный коэффициент не может быть нулевым или отрицательным."
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr "Неверный формат: введите данные как x, y, z"
 
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Неправильное выделение для ограничения 'отношение длин'.\n"
+#~ "Ограничение может принимать в качестве выделения следующие примитивы:\n"
+#~ "\n"
+#~ "    * два отрезка\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Неправильное выделение для ограничения 'разница длин'.\n"
+#~ "Ограничение может принимать в качестве выделения следующие примитивы:\n"
+#~ "\n"
+#~ "    * два отрезка\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "Отно&шение Длин"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "Ра&зница Длин"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Неправильное выделение для создания эскиза.\n"
+#~ "Группа может быть создана, используя в качестве выделения следующие "
+#~ "примитивы:\n"
+#~ "\n"
+#~ "    * точку (рабочая плоскость, ориентированная к ближайшему виду, "
+#~ "проходящая через точку)\n"
+#~ "    * точку и два отрезка (рабочая плоскость, проходящая через точку и "
+#~ "параллельная отрезкам)\n"
+#~ "    * рабочую плоскость (копия рабочей плоскости)\n"
+
 #~ msgid "Specify between 0 and 8 digits after the decimal."
 #~ msgstr "Введите число от 0 до 8."
 
diff --git a/res/locales/tr_TR.po b/res/locales/tr_TR.po
new file mode 100644 (file)
index 0000000..71558fc
--- /dev/null
@@ -0,0 +1,2302 @@
+# Turkish translations for SolveSpace package.
+# Copyright (C) 2017 the SolveSpace authors
+# This file is distributed under the same license as the SolveSpace package.
+# Automatically generated, 2017.
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: SolveSpace 3.0\n"
+"Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2022-02-01 23:02+0300\n"
+"Last-Translator: Mustafa Halil GÖRENTAŞ <halil.mustafa@gmail.com>\n"
+"Language-Team: app4soft\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.0\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: clipboard.cpp:309
+msgid ""
+"Cut, paste, and copy work only in a workplane.\n"
+"\n"
+"Activate one with Sketch -> In Workplane."
+msgstr ""
+"Çalışmayı yalnızca bir çalışma düzleminde kesin, yapıştırın ve kopyalayın.\n"
+"\n"
+"Çizim -> Çalışma Düzleminde menüsü ile bir düzlemi etkinleştirin."
+
+#: clipboard.cpp:326
+msgid "Clipboard is empty; nothing to paste."
+msgstr "Pano boş; yapıştırılacak bir şey yok."
+
+#: clipboard.cpp:373
+msgid "Number of copies to paste must be at least one."
+msgstr "Yapıştırılacak kopya sayısı en az bir olmalıdır."
+
+#: clipboard.cpp:389 textscreens.cpp:833
+msgid "Scale cannot be zero."
+msgstr "Ölçek sıfır olamaz."
+
+#: clipboard.cpp:431
+msgid "Select one point to define origin of rotation."
+msgstr "Çevirme merkezini tanımlamak için bir nokta seçin."
+
+#: clipboard.cpp:443
+msgid "Select two points to define translation vector."
+msgstr "Doğrusal kopyalama vektörünü tanımlamak için iki nokta seçin."
+
+#: clipboard.cpp:453
+msgid ""
+"Transformation is identity. So all copies will be exactly on top of each "
+"other."
+msgstr "Dönüşüm özdeştir. Yani tüm kopyalar tam olarak üst üste gelecek."
+
+#: clipboard.cpp:457
+msgid "Too many items to paste; split this into smaller pastes."
+msgstr ""
+"Yapıştırılamayacak kadar çok öğe; bunu daha küçük yapıştıma şeklinde bölün."
+
+#: clipboard.cpp:462
+msgid "No workplane active."
+msgstr "Etkin çalışma düzlemi yok."
+
+#: confscreen.cpp:381
+msgid "Bad format: specify coordinates as x, y, z"
+msgstr "Hatalı biçim: koordinatları x, y, z olarak belirtin"
+
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
+msgid "Bad format: specify color as r, g, b"
+msgstr "Hatalı biçim: rengi r, g, b olarak belirtin"
+
+#: confscreen.cpp:417
+msgid ""
+"The perspective factor will have no effect until you enable View -> Use "
+"Perspective Projection."
+msgstr ""
+"Görünüm -> Perspektif Projeksiyonu Kullan'ı etkinleştirene kadar perspektif "
+"katsayısının hiçbir etkisi olmayacaktır."
+
+#: confscreen.cpp:435 confscreen.cpp:445
+#, c-format
+msgid "Specify between 0 and %d digits after the decimal."
+msgstr "Ondalık basamak sonrası 0 ile %d arasında rakam belirtin."
+
+#: confscreen.cpp:457
+msgid "Export scale must not be zero!"
+msgstr "Dışa aktarma ölçeği sıfır olmamalıdır!"
+
+#: confscreen.cpp:469
+msgid "Cutter radius offset must not be negative!"
+msgstr "Kesici yarıçap ofseti negatif olmamalıdır!"
+
+#: confscreen.cpp:528
+msgid "Bad value: autosave interval should be positive"
+msgstr "Hatalı değer: otomatik kaydetme süresi pozitif olmalıdır"
+
+#: confscreen.cpp:531
+msgid "Bad format: specify interval in integral minutes"
+msgstr "Hatalı biçim: süre aralığını dakika cinsinden belirtin"
+
+#: constraint.cpp:12
+msgctxt "constr-name"
+msgid "pts-coincident"
+msgstr "çakışık-nktlar"
+
+#: constraint.cpp:13
+msgctxt "constr-name"
+msgid "pt-pt-distance"
+msgstr "nkt-nkt-mesafe"
+
+#: constraint.cpp:14
+msgctxt "constr-name"
+msgid "pt-line-distance"
+msgstr "nkt-çizgi-mesafesi"
+
+#: constraint.cpp:15
+msgctxt "constr-name"
+msgid "pt-plane-distance"
+msgstr "nkt-düzlem-mesafesi"
+
+#: constraint.cpp:16
+msgctxt "constr-name"
+msgid "pt-face-distance"
+msgstr "nkt-yüzey-mesafesi"
+
+#: constraint.cpp:17
+msgctxt "constr-name"
+msgid "proj-pt-pt-distance"
+msgstr "proj-nkt-nkt-mesafesi"
+
+#: constraint.cpp:18
+msgctxt "constr-name"
+msgid "pt-in-plane"
+msgstr "düzlemde-nkt"
+
+#: constraint.cpp:19
+msgctxt "constr-name"
+msgid "pt-on-line"
+msgstr "çizgide-nkt"
+
+#: constraint.cpp:20
+msgctxt "constr-name"
+msgid "pt-on-face"
+msgstr "yüzeyde-nkt"
+
+#: constraint.cpp:21
+msgctxt "constr-name"
+msgid "eq-length"
+msgstr "eşit-uzunluk"
+
+#: constraint.cpp:22
+msgctxt "constr-name"
+msgid "eq-length-and-pt-ln-dist"
+msgstr "eşit-uzunluk-ve-çzg-nkt-mesafesi"
+
+#: constraint.cpp:23
+msgctxt "constr-name"
+msgid "eq-pt-line-distances"
+msgstr "eşit-nkt-çizgi-mesafesi"
+
+#: constraint.cpp:24
+msgctxt "constr-name"
+msgid "length-ratio"
+msgstr "uzunluk-oranı"
+
+#: constraint.cpp:25
+msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr "yay-yay-uzunluk-oranı"
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr "yay-çizgi-uzunluk-oranı"
+
+#: constraint.cpp:27
+msgctxt "constr-name"
+msgid "length-difference"
+msgstr "uzunluk-farkı"
+
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr "yay-yay-uzunluk-farkı"
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr "yay-çizgi-uzunluk-farkı"
+
+#: constraint.cpp:30
+msgctxt "constr-name"
+msgid "symmetric"
+msgstr "simetrik"
+
+#: constraint.cpp:31
+msgctxt "constr-name"
+msgid "symmetric-h"
+msgstr "simetrik-y"
+
+#: constraint.cpp:32
+msgctxt "constr-name"
+msgid "symmetric-v"
+msgstr "simetrik-d"
+
+#: constraint.cpp:33
+msgctxt "constr-name"
+msgid "symmetric-line"
+msgstr "simetrik-çizgi"
+
+#: constraint.cpp:34
+msgctxt "constr-name"
+msgid "at-midpoint"
+msgstr "orta noktada"
+
+#: constraint.cpp:35
+msgctxt "constr-name"
+msgid "horizontal"
+msgstr "yatay"
+
+#: constraint.cpp:36
+msgctxt "constr-name"
+msgid "vertical"
+msgstr "dikey"
+
+#: constraint.cpp:37
+msgctxt "constr-name"
+msgid "diameter"
+msgstr "çap"
+
+#: constraint.cpp:38
+msgctxt "constr-name"
+msgid "pt-on-circle"
+msgstr "çemberde-nkt"
+
+#: constraint.cpp:39
+msgctxt "constr-name"
+msgid "same-orientation"
+msgstr "aynı-yön"
+
+#: constraint.cpp:40
+msgctxt "constr-name"
+msgid "angle"
+msgstr "açı"
+
+#: constraint.cpp:41
+msgctxt "constr-name"
+msgid "parallel"
+msgstr "paralel"
+
+#: constraint.cpp:42
+msgctxt "constr-name"
+msgid "arc-line-tangent"
+msgstr "yay-çizgi-teğet"
+
+#: constraint.cpp:43
+msgctxt "constr-name"
+msgid "cubic-line-tangent"
+msgstr "k.eğri-çizgi-teğet"
+
+#: constraint.cpp:44
+msgctxt "constr-name"
+msgid "curve-curve-tangent"
+msgstr "eğri-eğri-teğet"
+
+#: constraint.cpp:45
+msgctxt "constr-name"
+msgid "perpendicular"
+msgstr "dik"
+
+#: constraint.cpp:46
+msgctxt "constr-name"
+msgid "eq-radius"
+msgstr "eşit-yarıçap"
+
+#: constraint.cpp:47
+msgctxt "constr-name"
+msgid "eq-angle"
+msgstr "eşit-açı"
+
+#: constraint.cpp:48
+msgctxt "constr-name"
+msgid "eq-line-len-arc-len"
+msgstr "eşit-çizgi-uzn-yay-uzn"
+
+#: constraint.cpp:49
+msgctxt "constr-name"
+msgid "lock-where-dragged"
+msgstr "sürüklendiği-yerde-kilitli"
+
+#: constraint.cpp:50
+msgctxt "constr-name"
+msgid "comment"
+msgstr "yorum"
+
+#: constraint.cpp:144
+msgid ""
+"The tangent arc and line segment must share an endpoint. Constrain them with "
+"Constrain -> On Point before constraining tangent."
+msgstr ""
+"Teğet için yay ve çizgi parçası bir uç noktayı paylaşmalıdır. Teğet "
+"kısıtlamasından önce bunları Kısıtla -> Noktada ile kısıtlayın."
+
+#: constraint.cpp:163
+msgid ""
+"The tangent cubic and line segment must share an endpoint. Constrain them "
+"with Constrain -> On Point before constraining tangent."
+msgstr ""
+"Teğet için eğri ve çizgi parçası bir uç noktayı paylaşmalıdır. Teğet "
+"kısıtlamasından önce onları Kısıtla -> Noktada ile kısıtlayın."
+
+#: constraint.cpp:189
+msgid ""
+"The curves must share an endpoint. Constrain them with Constrain -> On Point "
+"before constraining tangent."
+msgstr ""
+"Eğriler bir uç noktayı paylaşmalıdır. Teğet kısıtlamasından önce onları "
+"Kısıtla -> Noktada ile kısıtlayın."
+
+#: constraint.cpp:238
+msgid ""
+"Bad selection for distance / diameter constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two points (distance between points)\n"
+"    * a line segment (length)\n"
+"    * two points and a line segment or normal (projected distance)\n"
+"    * a workplane and a point (minimum distance)\n"
+"    * a line segment and a point (minimum distance)\n"
+"    * a plane face and a point (minimum distance)\n"
+"    * a circle or an arc (diameter)\n"
+msgstr ""
+"Mesafe / çap kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * iki nokta (noktalar arası mesafe)\n"
+"    * bir çizgi parçası (uzunluk)\n"
+"    * iki nokta ve bir çizgi parçası veya normal (izdüşüm mesafesi)\n"
+"    * bir çalışma düzlemi ve bir nokta (minimum mesafe)\n"
+"    * bir çizgi parçası ve bir nokta (minimum mesafe)\n"
+"    * bir düzlem yüzeyi ve bir nokta (minimum mesafe)\n"
+"    * bir daire veya yay (çap)\n"
+
+#: constraint.cpp:291
+msgid ""
+"Bad selection for on point / curve / plane constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two points (points coincident)\n"
+"    * a point and a workplane (point in plane)\n"
+"    * a point and a line segment (point on line)\n"
+"    * a point and a circle or arc (point on curve)\n"
+"    * a point and a plane face (point on face)\n"
+msgstr ""
+"Noktada / Eğride / Düzlemde kısıtlaması oluşturmak için hatalı seçim. Bu "
+"kısıtlama şunlara uygulanabilir:\n"
+"\n"
+"    * iki nokta (çakışan noktalar)\n"
+"    * bir nokta ve bir çalışma düzlemi (nokta ile düzlem çakışır)\n"
+"    * bir nokta ve bir çizgi parçası (nokta ile çizgi çakışır)\n"
+"    * bir nokta ve bir daire veya yay (nokta ile eğri çakışır)\n"
+"    * bir nokta ve bir düzlem yüzeyi (nokta ile yüzey çakışır)\n"
+
+#: constraint.cpp:353
+msgid ""
+"Bad selection for equal length / radius constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two line segments (equal length)\n"
+"    * two line segments and two points (equal point-line distances)\n"
+"    * a line segment and two points (equal point-line distances)\n"
+"    * a line segment, and a point and line segment (point-line distance "
+"equals length)\n"
+"    * four line segments or normals (equal angle between A,B and C,D)\n"
+"    * three line segments or normals (equal angle between A,B and B,C)\n"
+"    * two circles or arcs (equal radius)\n"
+"    * a line segment and an arc (line segment length equals arc length)\n"
+msgstr ""
+"Eşit uzunluk / yarıçap kısıtlaması oluşturmak için hatalı seçim. Bu "
+"kısıtlama şunlara uygulanabilir:\n"
+"\n"
+"    * iki çizgi parçası (eşit uzunluk)\n"
+"    * iki çizgi parçası ve iki nokta (eşit nokta-çizgi arası mesafeler)\n"
+"    * bir çizgi parçası ve iki nokta (eşit nokta-çizgi arası mesafeler)\n"
+"    * bir çizgi parçası ve bir nokta ve çizgi parçası (nokta-çizgi arası "
+"mesafe, çizgi uzunluğa eşittir)\n"
+"    * dört çizgi parçası veya normal (A, B ve C, D arasında eşit açı)\n"
+"    * üç çizgi parçası veya normal (A, B ve B, C arasında eşit açı)\n"
+"    * iki daire veya yay (eşit yarıçap)\n"
+"    * bir çizgi parçası ve bir yay (çizgi parçasının uzunluğu, yayın "
+"uzunluğuna eşittir)\n"
+
+#: constraint.cpp:407
+msgid ""
+"Bad selection for length ratio constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
+msgstr ""
+"Uzunluk oranı kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama "
+"aşağıdakiler için geçerli olabilir:\n"
+"\n"
+"    * iki çizgi parçası\n"
+"    * iki yay\n"
+"    * bir yay ve bir çizgi parçası\n"
+
+#: constraint.cpp:441
+msgid ""
+"Bad selection for length difference constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
+msgstr ""
+"Uzunluk farkı kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama "
+"aşağıdakiler için geçerli olabilir:\n"
+"\n"
+"    * iki çizgi parçası\n"
+"    * iki yay\n"
+"    * bir yay ve bir çizgi parçası\n"
+
+#: constraint.cpp:472
+msgid ""
+"Bad selection for at midpoint constraint. This constraint can apply to:\n"
+"\n"
+"    * a line segment and a point (point at midpoint)\n"
+"    * a line segment and a workplane (line's midpoint on plane)\n"
+msgstr ""
+"Orta nokta kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * bir çizgi parçası ve bir nokta (nokta çizgi ortasında)\n"
+"    * bir çizgi parçası ve bir çalışma düzlemi (çizgi düzlemin ortasına "
+"taşınır )\n"
+
+#: constraint.cpp:530
+msgid ""
+"Bad selection for symmetric constraint. This constraint can apply to:\n"
+"\n"
+"    * two points or a line segment (symmetric about workplane's coordinate "
+"axis)\n"
+"    * line segment, and two points or a line segment (symmetric about line "
+"segment)\n"
+"    * workplane, and two points or a line segment (symmetric about "
+"workplane)\n"
+msgstr ""
+"Simetri kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * iki nokta veya bir çizgi parçası (çalışma düzleminin koordinat "
+"eksenine göre simetrik)\n"
+"    * çizgi parçası ve iki nokta veya bir çizgi parçası (çizgi parçası "
+"etrafında simetrik)\n"
+"    * çalışma düzlemi ve iki nokta veya bir çizgi parçası (çalışma düzlemine "
+"göre simetrik)\n"
+
+#: constraint.cpp:545
+msgid ""
+"A workplane must be active when constraining symmetric without an explicit "
+"symmetry plane."
+msgstr ""
+"Simetri kısıtlamasında simetri düzlemini olarak kullanılacak bir çalışma "
+"düzlemi etkin olmalıdır."
+
+#: constraint.cpp:579
+msgid ""
+"Activate a workplane (with Sketch -> In Workplane) before applying a "
+"horizontal or vertical constraint."
+msgstr ""
+"Yatay veya dikey bir kısıtlama uygulamadan önce bir çalışma düzlemini (Çizim "
+"-> Çalışma Düzleminde menüsü ile) etkinleştirin."
+
+#: constraint.cpp:592
+msgid ""
+"Bad selection for horizontal / vertical constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * two points\n"
+"    * a line segment\n"
+msgstr ""
+"Yatay / Dikey kısıtlama oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * iki nokta\n"
+"    * bir çizgi parçası\n"
+
+#: constraint.cpp:613
+msgid ""
+"Bad selection for same orientation constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two normals\n"
+msgstr ""
+"Aynı yön kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * iki normal\n"
+
+#: constraint.cpp:663
+msgid "Must select an angle constraint."
+msgstr "Bir açı kısıtlaması seçilmelidir."
+
+#: constraint.cpp:676
+msgid "Must select a constraint with associated label."
+msgstr "İlgili etikete sahip bir kısıtlama seçilmelidir."
+
+#: constraint.cpp:687
+msgid ""
+"Bad selection for angle constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * a line segment and a normal\n"
+"    * two normals\n"
+msgstr ""
+"Açı kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"    * iki çizgi parçası\n"
+"    * bir çizgi parçası ve normal\n"
+"    * iki normal\n"
+
+#: constraint.cpp:754
+msgid "Curve-curve tangency must apply in workplane."
+msgstr "Eğri-eğri teğetliği çalışma düzlemine uygulanmalıdır."
+
+#: constraint.cpp:766
+msgid ""
+"Bad selection for parallel / tangent constraint. This constraint can apply "
+"to:\n"
+"\n"
+"    * two line segments (parallel)\n"
+"    * a line segment and a normal (parallel)\n"
+"    * two normals (parallel)\n"
+"    * two line segments, arcs, or beziers, that share an endpoint (tangent)\n"
+msgstr ""
+"Paralel / Teğet kısıtlaması oluşturmak için hatalı seçim. Bu kısıtlama "
+"şunlara uygulanabilir:\n"
+"\n"
+"    * iki çizgi parçası (paralel)\n"
+"    * bir çizgi parçası ve normal (paralel)\n"
+"    * iki normal (paralel)\n"
+"    * bir uç noktayı paylaşan(teğet) iki çizgi parçası, yay veya bezier'ler\n"
+
+#: constraint.cpp:784
+msgid ""
+"Bad selection for perpendicular constraint. This constraint can apply to:\n"
+"\n"
+"    * two line segments\n"
+"    * a line segment and a normal\n"
+"    * two normals\n"
+msgstr ""
+"Dikey kısıtlama oluşturmak için hatalı seçim. Bu kısıtlama şunlara "
+"uygulanabilir:\n"
+"\n"
+"     * iki çizgi parçası\n"
+"     * bir çizgi parçası ve normal\n"
+"     * iki normal\n"
+
+#: constraint.cpp:799
+msgid ""
+"Bad selection for lock point where dragged constraint. This constraint can "
+"apply to:\n"
+"\n"
+"    * a point\n"
+msgstr ""
+"Sürüklendiği yerde noktayı kısıtlamak için hatalı seçim. Bu kısıtlama "
+"şunlara uygulanabilir:\n"
+"\n"
+"* bir nokta\n"
+
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "YENI YORUM -- DÜZENLEMEK ICIN CIFT-TIKLAYIN"
+
+#: constraint.cpp:818
+msgid "click center of comment text"
+msgstr "yorum metninin ortasını tıklatın"
+
+#: export.cpp:19
+msgid ""
+"No solid model present; draw one with extrudes and revolves, or use Export "
+"2d View to export bare lines and curves."
+msgstr ""
+"Katı model yok; katılama ve döndürme komutları ile bir model çizin veya açık "
+"çizgileri ve eğrileri dışa vermek için Görüntüyü 2d olarak Dışa Aktar'ı "
+"kullanın."
+
+#: export.cpp:61
+msgid ""
+"Bad selection for export section. Please select:\n"
+"\n"
+"    * nothing, with an active workplane (workplane is section plane)\n"
+"    * a face (section plane through face)\n"
+"    * a point and two line segments (plane through point and parallel to "
+"lines)\n"
+msgstr ""
+"Kesiti Dışa Aktarmak için hatalı seçim. Lütfen şunlardan birini seçin:\n"
+"\n"
+"    * aktif bir çalışma düzleminde iken hiçbir şey seçmeyin (çalışma "
+"düzlemi, kesit düzlemidir)\n"
+"    * bir yüzey (yüzeyden kesit düzlemi)\n"
+"    * bir nokta ve iki çizgi parçası (nokta ve paralel çizgiler boyunca "
+"düzlem)\n"
+
+#: export.cpp:818
+msgid "Active group mesh is empty; nothing to export."
+msgstr "Etkin grup ağı boş; dışa aktarılacak bir şey yok."
+
+#: exportvector.cpp:336
+msgid "freehand lines were replaced with continuous lines"
+msgstr "serbest çizgiler, sürekli çizgilerle değiştirildi"
+
+#: exportvector.cpp:338
+msgid "zigzag lines were replaced with continuous lines"
+msgstr "zikzak çizgiler sürekli çizgilerle değiştirildi"
+
+#: exportvector.cpp:592
+msgid ""
+"Some aspects of the drawing have no DXF equivalent and were not exported:\n"
+msgstr "Çizimin bazı yönlerinin DXF eşdeğeri yoktur ve dışa aktarılmamıştır:\n"
+
+#: exportvector.cpp:838
+msgid ""
+"PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
+msgstr ""
+"PDF sayfa boyutu 200 x 200 inç'i aşıyor; birçok görüntüleyici bu dosyayı "
+"reddedebilir."
+
+#: file.cpp:44 group.cpp:91
+msgctxt "group-name"
+msgid "sketch-in-plane"
+msgstr "düzlemde çizim"
+
+#: file.cpp:62
+msgctxt "group-name"
+msgid "#references"
+msgstr "#referanslar"
+
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "Dosya boş. Bozuk olabilir."
+
+#: file.cpp:555
+msgid ""
+"Unrecognized data in file. This file may be corrupt, or from a newer version "
+"of the program."
+msgstr ""
+"Dosyada veriler tanınmadı. Bu dosya bozuk veya programın daha yeni bir "
+"sürümü ile oluşturulmuş olabilir."
+
+#: file.cpp:867
+msgctxt "title"
+msgid "Missing File"
+msgstr "Kayıp Dosya"
+
+#: file.cpp:868
+#, c-format
+msgctxt "dialog"
+msgid "The linked file “%s” is not present."
+msgstr "\"%s\" bağlantılı dosya yok."
+
+#: file.cpp:870
+msgctxt "dialog"
+msgid ""
+"Do you want to locate it manually?\n"
+"\n"
+"If you decline, any geometry that depends on the missing file will be "
+"permanently removed."
+msgstr ""
+"Konumu El ile bulmak istiyor musunuz?\n"
+"\n"
+"Reddederseniz, eksik dosyaya bağlı olan geometri kalıcı olarak "
+"kaldırılacaktır."
+
+#: file.cpp:873
+msgctxt "button"
+msgid "&Yes"
+msgstr "&Evet"
+
+#: file.cpp:875
+msgctxt "button"
+msgid "&No"
+msgstr "&Hayır"
+
+#: file.cpp:877 solvespace.cpp:611
+msgctxt "button"
+msgid "&Cancel"
+msgstr "&İptal"
+
+#: graphicswin.cpp:41
+msgid "&File"
+msgstr "&Dosya"
+
+#: graphicswin.cpp:42
+msgid "&New"
+msgstr "&Yeni"
+
+#: graphicswin.cpp:43
+msgid "&Open..."
+msgstr "&Aç..."
+
+#: graphicswin.cpp:44
+msgid "Open &Recent"
+msgstr "&Son Erişilenden Aç"
+
+#: graphicswin.cpp:45
+msgid "&Save"
+msgstr "&Kaydet"
+
+#: graphicswin.cpp:46
+msgid "Save &As..."
+msgstr "&Farklı kaydet..."
+
+#: graphicswin.cpp:48
+msgid "Export &Image..."
+msgstr "&Resim olarak dışa aktar..."
+
+#: graphicswin.cpp:49
+msgid "Export 2d &View..."
+msgstr "&Görüntüyü 2d olarak dışa aktar..."
+
+#: graphicswin.cpp:50
+msgid "Export 2d &Section..."
+msgstr "&Kesiti 2d olarak dışa aktar..."
+
+#: graphicswin.cpp:51
+msgid "Export 3d &Wireframe..."
+msgstr "3d &TelKafes olarak dışa aktar..."
+
+#: graphicswin.cpp:52
+msgid "Export Triangle &Mesh..."
+msgstr "&Üçgensel Ağ olarak dışa aktar..."
+
+#: graphicswin.cpp:53
+msgid "Export &Surfaces..."
+msgstr "Y&üzeyleri dışa aktar..."
+
+#: graphicswin.cpp:54
+msgid "Im&port..."
+msgstr "&İçe Aktar..."
+
+#: graphicswin.cpp:57
+msgid "E&xit"
+msgstr "&Çıkış"
+
+#: graphicswin.cpp:60
+msgid "&Edit"
+msgstr "D&üzen"
+
+#: graphicswin.cpp:61
+msgid "&Undo"
+msgstr "&Geri al"
+
+#: graphicswin.cpp:62
+msgid "&Redo"
+msgstr "&Yinele"
+
+#: graphicswin.cpp:63
+msgid "Re&generate All"
+msgstr "Tümünü Yeniden &Oluştur"
+
+#: graphicswin.cpp:65
+msgid "Snap Selection to &Grid"
+msgstr "Seçimi &Izgaraya Tuttur"
+
+#: graphicswin.cpp:66
+msgid "Rotate Imported &90°"
+msgstr "İçe Aktarılanları &90° Döndür"
+
+#: graphicswin.cpp:68
+msgid "Cu&t"
+msgstr "&Kes"
+
+#: graphicswin.cpp:69
+msgid "&Copy"
+msgstr "K&opyala"
+
+#: graphicswin.cpp:70
+msgid "&Paste"
+msgstr "Y&apıştır"
+
+#: graphicswin.cpp:71
+msgid "Paste &Transformed..."
+msgstr "&Dönüştürerek Yapıştır..."
+
+#: graphicswin.cpp:72
+msgid "&Delete"
+msgstr "&Sil"
+
+#: graphicswin.cpp:74
+msgid "Select &Edge Chain"
+msgstr "Kenar &Zincirini Seç"
+
+#: graphicswin.cpp:75
+msgid "Select &All"
+msgstr "&Tümünü Seç"
+
+#: graphicswin.cpp:76
+msgid "&Unselect All"
+msgstr "Tüm Seçimi &Kaldır"
+
+#: graphicswin.cpp:78
+msgid "&Line Styles..."
+msgstr "&Çizgi Biçimi..."
+
+#: graphicswin.cpp:79
+msgid "&View Projection..."
+msgstr "&Projeksiyonu Görüntüle..."
+
+#: graphicswin.cpp:81
+msgid "Con&figuration..."
+msgstr "Y&apılandır..."
+
+#: graphicswin.cpp:84
+msgid "&View"
+msgstr "&Görünüm"
+
+#: graphicswin.cpp:85
+msgid "Zoom &In"
+msgstr "&Yakınlaş"
+
+#: graphicswin.cpp:86
+msgid "Zoom &Out"
+msgstr "&Uzaklaş"
+
+#: graphicswin.cpp:87
+msgid "Zoom To &Fit"
+msgstr "&Sığacak Şekilde Yakınlaş"
+
+#: graphicswin.cpp:89
+msgid "Align View to &Workplane"
+msgstr "Görünümü &Çalışma Düzlemine Hizala"
+
+#: graphicswin.cpp:90
+msgid "Nearest &Ortho View"
+msgstr "En Yakın &Dik Görünüm"
+
+#: graphicswin.cpp:91
+msgid "Nearest &Isometric View"
+msgstr "En Yakın &İzometrik Görünüm"
+
+#: graphicswin.cpp:92
+msgid "&Center View At Point"
+msgstr "&Noktayı Merkezde Görüntüle"
+
+#: graphicswin.cpp:94
+msgid "Show Snap &Grid"
+msgstr "Yakalama &Izgarasını Göster"
+
+#: graphicswin.cpp:95
+msgid "Darken Inactive Solids"
+msgstr "Aktif Olmayan Katıları &Koyulaştır"
+
+#: graphicswin.cpp:96
+msgid "Use &Perspective Projection"
+msgstr "&Perspektif Projeksiyonu Kullan"
+
+#: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr "Pat&latılmış Görünümü Göster"
+
+#: graphicswin.cpp:98
+msgid "Dimension &Units"
+msgstr "Ölçü &Birimleri"
+
+#: graphicswin.cpp:99
+msgid "Dimensions in &Millimeters"
+msgstr "&Milimetre cinsinden ölçü"
+
+#: graphicswin.cpp:100
+msgid "Dimensions in M&eters"
+msgstr "M&etre cinsinden ölçü"
+
+#: graphicswin.cpp:101
+msgid "Dimensions in &Inches"
+msgstr "&İnç cinsinden ölçü"
+
+#: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr "&Fit ve İnç cinsinden ölçü"
+
+#: graphicswin.cpp:104
+msgid "Show &Toolbar"
+msgstr "&Araç Çubuğunu Göster"
+
+#: graphicswin.cpp:105
+msgid "Show Property Bro&wser"
+msgstr "&Özellik Penceresini Göster"
+
+#: graphicswin.cpp:107
+msgid "&Full Screen"
+msgstr "&Tam Ekran"
+
+#: graphicswin.cpp:109
+msgid "&New Group"
+msgstr "Yeni &Grup"
+
+#: graphicswin.cpp:110
+msgid "Sketch In &3d"
+msgstr "&3d'de Çizim Yap"
+
+#: graphicswin.cpp:111
+msgid "Sketch In New &Workplane"
+msgstr "&Yeni Çalışma Düzleminde Çizim Yap"
+
+#: graphicswin.cpp:113
+msgid "Step &Translating"
+msgstr "&Doğrusal Kopya"
+
+#: graphicswin.cpp:114
+msgid "Step &Rotating"
+msgstr "D&airesel Kopya"
+
+#: graphicswin.cpp:116
+msgid "E&xtrude"
+msgstr "&Uzatarak Katıla"
+
+#: graphicswin.cpp:117
+msgid "&Helix"
+msgstr "&Helis"
+
+#: graphicswin.cpp:118
+msgid "&Lathe"
+msgstr "&Tam döndürerek katıla"
+
+#: graphicswin.cpp:119
+msgid "Re&volve"
+msgstr "&Kısmen döndürerek katıla"
+
+#: graphicswin.cpp:121
+msgid "Link / Assemble..."
+msgstr "Bağla / Montajla..."
+
+#: graphicswin.cpp:122
+msgid "Link Recent"
+msgstr "Son Erişilenden Bağla"
+
+#: graphicswin.cpp:124
+msgid "&Sketch"
+msgstr "&Çizim"
+
+#: graphicswin.cpp:125
+msgid "In &Workplane"
+msgstr "Ç&alışma Düzleminde"
+
+#: graphicswin.cpp:126
+msgid "Anywhere In &3d"
+msgstr "&3d'de Herhangi Bir Yerde"
+
+#: graphicswin.cpp:128
+msgid "Datum &Point"
+msgstr "Referasn &Noktası"
+
+#: graphicswin.cpp:129
+msgid "&Workplane"
+msgstr "Ça&lışma Düzlemi"
+
+#: graphicswin.cpp:131
+msgid "Line &Segment"
+msgstr "Ç&izgi"
+
+#: graphicswin.cpp:132
+msgid "C&onstruction Line Segment"
+msgstr "&Yardımcı Çizgi"
+
+#: graphicswin.cpp:133
+msgid "&Rectangle"
+msgstr "&Dikdörtgen"
+
+#: graphicswin.cpp:134
+msgid "&Circle"
+msgstr "D&aire"
+
+#: graphicswin.cpp:135
+msgid "&Arc of a Circle"
+msgstr "Çember &Yayı"
+
+#: graphicswin.cpp:136
+msgid "&Bezier Cubic Spline"
+msgstr "Bezier Kübik &Eğri"
+
+#: graphicswin.cpp:138
+msgid "&Text in TrueType Font"
+msgstr "TrueType Yazı Tipinde &Metin"
+
+#: graphicswin.cpp:139
+msgid "&Image"
+msgstr "&Resim / Görüntü"
+
+#: graphicswin.cpp:141
+msgid "To&ggle Construction"
+msgstr "Yap&ıyı Değiştir"
+
+#: graphicswin.cpp:142
+msgid "Tangent &Arc at Point"
+msgstr "&Yuvarlat (Radyus)"
+
+#: graphicswin.cpp:143
+msgid "Split Curves at &Intersection"
+msgstr "Eğrileri Kesişim Yerinden &Böl"
+
+#: graphicswin.cpp:145
+msgid "&Constrain"
+msgstr "&Kısıtla"
+
+#: graphicswin.cpp:146
+msgid "&Distance / Diameter"
+msgstr "&Mesafe / Çap"
+
+#: graphicswin.cpp:147
+msgid "Re&ference Dimension"
+msgstr "&Referans Ölçü"
+
+#: graphicswin.cpp:148
+msgid "A&ngle"
+msgstr "&Açı"
+
+#: graphicswin.cpp:149
+msgid "Reference An&gle"
+msgstr "Referans A&çı"
+
+#: graphicswin.cpp:150
+msgid "Other S&upplementary Angle"
+msgstr "Diğer &Bütünler Açı"
+
+#: graphicswin.cpp:151
+msgid "Toggle R&eference Dim"
+msgstr "Ölçüyü Re&ferans Yap / Yapma"
+
+#: graphicswin.cpp:153
+msgid "&Horizontal"
+msgstr "&Yatay"
+
+#: graphicswin.cpp:154
+msgid "&Vertical"
+msgstr "&Dikey"
+
+#: graphicswin.cpp:156
+msgid "&On Point / Curve / Plane"
+msgstr "&Noktada / Eğride / Düzlemde"
+
+#: graphicswin.cpp:157
+msgid "E&qual Length / Radius / Angle"
+msgstr "&Eşit Uzunluk / Yarıçap / Açı"
+
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr "&Uzunluk / Yay Oranı"
+
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr "Uzunluk / Yay &Farkı"
+
+#: graphicswin.cpp:160
+msgid "At &Midpoint"
+msgstr "&Orta Noktada"
+
+#: graphicswin.cpp:161
+msgid "S&ymmetric"
+msgstr "&Simetrik"
+
+#: graphicswin.cpp:162
+msgid "Para&llel / Tangent"
+msgstr "&Paralel / Teğet"
+
+#: graphicswin.cpp:163
+msgid "&Perpendicular"
+msgstr "D&ik"
+
+#: graphicswin.cpp:164
+msgid "Same Orient&ation"
+msgstr "Aynı &Yön"
+
+#: graphicswin.cpp:165
+msgid "Lock Point Where &Dragged"
+msgstr "Sürüklendiği Yerde Noktayı &Kilitle"
+
+#: graphicswin.cpp:167
+msgid "Comment"
+msgstr "Y&orum"
+
+#: graphicswin.cpp:169
+msgid "&Analyze"
+msgstr "&Analiz"
+
+#: graphicswin.cpp:170
+msgid "Measure &Volume"
+msgstr "&Hacmi Hesapla"
+
+#: graphicswin.cpp:171
+msgid "Measure A&rea"
+msgstr "&Alanı Hesapla"
+
+#: graphicswin.cpp:172
+msgid "Measure &Perimeter"
+msgstr "&Çevre Uzunluğunu Hesapla"
+
+#: graphicswin.cpp:173
+msgid "Show &Interfering Parts"
+msgstr "&Engelleyici Parçaları Göster"
+
+#: graphicswin.cpp:174
+msgid "Show &Naked Edges"
+msgstr "A&çık Kenarları Göster"
+
+#: graphicswin.cpp:175
+msgid "Show &Center of Mass"
+msgstr "&Kütle Merkezini Göster"
+
+#: graphicswin.cpp:177
+msgid "Show &Underconstrained Points"
+msgstr "Kı&sıtlanmamış Noktaları Göster"
+
+#: graphicswin.cpp:179
+msgid "&Trace Point"
+msgstr "&İzlenecek Nokta"
+
+#: graphicswin.cpp:180
+msgid "&Stop Tracing..."
+msgstr "&İzlemeyi Durdur..."
+
+#: graphicswin.cpp:181
+msgid "Step &Dimension..."
+msgstr "Adım &Ölçüsünü Ayarla..."
+
+#: graphicswin.cpp:183
+msgid "&Help"
+msgstr "&Yardım"
+
+#: graphicswin.cpp:184
+msgid "&Language"
+msgstr "&Dil"
+
+#: graphicswin.cpp:185
+msgid "&Website / Manual"
+msgstr "&Web sitesi / Kılavuz"
+
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr "GitHub Commitlere git"
+
+#: graphicswin.cpp:188
+msgid "&About"
+msgstr "&Hakkında"
+
+#: graphicswin.cpp:362
+msgid "(no recent files)"
+msgstr "(son dosyalar yok)"
+
+#: graphicswin.cpp:370
+#, c-format
+msgid "File '%s' does not exist."
+msgstr "'%s' dosyası mevcut değil."
+
+#: graphicswin.cpp:737
+msgid "No workplane is active, so the grid will not appear."
+msgstr "Etkin çalışma düzlemi yok, bu nedenle ızgara görünmeyecektir."
+
+#: graphicswin.cpp:752
+msgid ""
+"The perspective factor is set to zero, so the view will always be a parallel "
+"projection.\n"
+"\n"
+"For a perspective projection, modify the perspective factor in the "
+"configuration screen. A value around 0.3 is typical."
+msgstr ""
+"Perspektif katsayısı sıfıra ayarlanmıştır, bu nedenle görünüm her zaman "
+"paralel bir projeksiyon olacaktır.\n"
+"\n"
+"Perspektif bir projeksiyon için, yapılandırma ekranındaki perspektif "
+"katsayısını değiştirin. 0.3 civarında bir değer normaldir."
+
+#: graphicswin.cpp:837
+msgid ""
+"Select a point; this point will become the center of the view on screen."
+msgstr "Bir nokta seçin; bu nokta ekrandaki görüntünün merkezi olacaktır."
+
+#: graphicswin.cpp:1137
+msgid "No additional entities share endpoints with the selected entities."
+msgstr "Hiçbir ek öğe, seçili öğeler ile uç noktaları paylaşmıyor."
+
+#: graphicswin.cpp:1155
+msgid ""
+"To use this command, select a point or other entity from an linked part, or "
+"make a link group the active group."
+msgstr ""
+"Bu komutu kullanmak için, bağlantılı bir parçadan bir nokta veya başka bir "
+"öğe seçin veya bir bağlantı grubunu etkin grup haline getirin."
+
+#: graphicswin.cpp:1178
+msgid ""
+"No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
+"to define the plane for the snap grid."
+msgstr ""
+"Hiçbir çalışma düzlemi etkin değil. Izgaranın yakalanacağı düzlemini "
+"tanımlamak için bir çalışma düzlemini (Çizim -> Çalışma Düzleminde ile) "
+"etkinleştirin."
+
+#: graphicswin.cpp:1185
+msgid ""
+"Can't snap these items to grid; select points, text comments, or constraints "
+"with a label. To snap a line, select its endpoints."
+msgstr ""
+"Bu öğeler ızgaraya tutturulamıyor; etiketli noktaları, metin yorumlarını "
+"veya kısıtlamaları seçin. Bir çizgiyi tutturmak için uç noktalarını seçin."
+
+#: graphicswin.cpp:1270
+msgid "No workplane selected. Activating default workplane for this group."
+msgstr ""
+"Çalışma düzlemi seçilmedi. Bu grup için varsayılan çalışma düzlemi "
+"etkinleştiriliyor."
+
+#: graphicswin.cpp:1273
+msgid ""
+"No workplane is selected, and the active group does not have a default "
+"workplane. Try selecting a workplane, or activating a sketch-in-new-"
+"workplane group."
+msgstr ""
+"Hiçbir çalışma düzlemi seçilmedi ve aktif grubun varsayılan bir çalışma "
+"düzlemi yok. Bir çalışma düzlemi seçmeyi veya bir yeni çalışma düzleminde "
+"çizim grubunu etkinleştirmeyi deneyin."
+
+#: graphicswin.cpp:1294
+msgid ""
+"Bad selection for tangent arc at point. Select a single point, or select "
+"nothing to set up arc parameters."
+msgstr ""
+"Noktada teğet yay (radyus) oluşturmak için hatalı seçim. Tek bir nokta seçin "
+"veya yay parametrelerini ayarlamak için hiçbir şey seçmeyin."
+
+#: graphicswin.cpp:1305
+msgid "click point on arc (draws anti-clockwise)"
+msgstr "yayın ilk noktası için tıklayın (saat yönünün tersine çizilir)"
+
+#: graphicswin.cpp:1306
+msgid "click to place datum point"
+msgstr "referans noktayı yerleştirmek için tıklayın"
+
+#: graphicswin.cpp:1307
+msgid "click first point of line segment"
+msgstr "çizgi parçasının ilk noktası için tıklayın"
+
+#: graphicswin.cpp:1309
+msgid "click first point of construction line segment"
+msgstr "yardımcı çizginin ilk noktası için tıklayın"
+
+#: graphicswin.cpp:1310
+msgid "click first point of cubic segment"
+msgstr "kübik eğri parçanın ilk noktası için tıklayın"
+
+#: graphicswin.cpp:1311
+msgid "click center of circle"
+msgstr "dairenin merkez konumu için tıklayın"
+
+#: graphicswin.cpp:1312
+msgid "click origin of workplane"
+msgstr "çalışma düzleminin merkez konumu için tıklayın"
+
+#: graphicswin.cpp:1313
+msgid "click one corner of rectangle"
+msgstr "dikdörtgenin bir köşe noktası için tıklayın"
+
+#: graphicswin.cpp:1314
+msgid "click top left of text"
+msgstr "metnin sol üst köşe konumu için tıklayın"
+
+#: graphicswin.cpp:1320
+msgid "click top left of image"
+msgstr "görüntünün sol üst köşe konumu için tıklayın"
+
+#: graphicswin.cpp:1346
+msgid ""
+"No entities are selected. Select entities before trying to toggle their "
+"construction state."
+msgstr ""
+"Hiçbir öğe seçilmedi. Yapı durumlarını değiştirmeye çalışmadan önce öğeleri "
+"seçin."
+
+#: group.cpp:86
+msgctxt "group-name"
+msgid "sketch-in-3d"
+msgstr "3d-de-çizim"
+
+#: group.cpp:150
+msgid ""
+"Bad selection for new sketch in workplane. This group can be created with:\n"
+"\n"
+"    * a point (through the point, orthogonal to coordinate axes)\n"
+"    * a point and two line segments (through the point, parallel to the "
+"lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
+"    * a workplane (copy of the workplane)\n"
+msgstr ""
+"Çalışma düzleminde yeni çizim oluşturmak için hatalı seçim. Bu grup "
+"aşağıdakilerle oluşturulabilir:\n"
+"\n"
+"    * bir nokta (noktadan geçen, koordinat eksenine dik)\n"
+"    * bir nokta ve iki doğru parçası (noktadan geçen, doğrulara paralel)\n"
+"    * bir nokta ve bir normal (noktadan normale dik)\n"
+"    * bir çalışma düzlemi (çalışma düzleminin kopyası)\n"
+
+#: group.cpp:166
+msgid ""
+"Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
+"will be extruded normal to the workplane."
+msgstr ""
+"Katılama işleminden önce bir çalışma düzlemini  etkinleştirin. Çizim, "
+"çalışma düzlemine dik olarak katılanacaktır."
+
+#: group.cpp:175
+msgctxt "group-name"
+msgid "extrude"
+msgstr "doğrusal katıla"
+
+#: group.cpp:180
+msgid "Lathe operation can only be applied to planar sketches."
+msgstr ""
+"Tam tur döndürerek katılama işlemi, yalnızca düzlemsel çizimlere "
+"uygulanabilir."
+
+#: group.cpp:191
+msgid ""
+"Bad selection for new lathe group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Tamamen döndürerek yeni katılama grubu oluşturmak için hatalı seçim. Bu grup "
+"şu şekilde oluşturulabilir:\n"
+"\n"
+"    * bir nokta ve bir çizgi parçası veya normal (çizgiye / normale paralel "
+"bir eksen etrafında, nokta boyunca döndürülür )\n"
+"    * bir çizgi parçası (çizgi parçası etrafında döndürülür)\n"
+
+#: group.cpp:201
+msgctxt "group-name"
+msgid "lathe"
+msgstr "tamamen döndürerek katıla"
+
+#: group.cpp:206
+msgid "Revolve operation can only be applied to planar sketches."
+msgstr ""
+"Kısmen döndürerek katılama işlemi, yalnızca düzlemsel çizimlere "
+"uygulanabilir."
+
+#: group.cpp:217
+msgid ""
+"Bad selection for new revolve group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Kısmen döndürerek yeni katılama grubu oluşturmak için hatalı seçim. Bu grup "
+"şu şekilde oluşturulabilir:\n"
+"\n"
+"\n"
+"    * bir nokta ve bir çizgi parçası veya normal (çizgiye / normale paralel, "
+"noktadan geçen bir eksen etrafında döndürülür)\n"
+"    * bir çizgi parçası (çizgi parçası etrafında döndürülür)\n"
+
+#: group.cpp:229
+msgctxt "group-name"
+msgid "revolve"
+msgstr "kısmen döndürerek katıla"
+
+#: group.cpp:234
+msgid "Helix operation can only be applied to planar sketches."
+msgstr "Helis işlemi yalnızca düzlemsel çizimlere uygulanabilir."
+
+#: group.cpp:245
+msgid ""
+"Bad selection for new helix group. This group can be created with:\n"
+"\n"
+"    * a point and a line segment or normal (revolved about an axis parallel "
+"to line / normal, through point)\n"
+"    * a line segment (revolved about line segment)\n"
+msgstr ""
+"Yeni helis grubu oluşturmak için hatalı seçim. Bu grup şunlarla "
+"oluşturulabilir:\n"
+"\n"
+"    * bir nokta ve bir çizgi parçası veya normal (çizgiye / normale paralel, "
+"noktadan geçen bir eksen etrafında döndürülür)\n"
+"    * bir çizgi parçası (çizgi parçası etrafında döndürülür)\n"
+
+#: group.cpp:257
+msgctxt "group-name"
+msgid "helix"
+msgstr "helis"
+
+#: group.cpp:270
+msgid ""
+"Bad selection for new rotation. This group can be created with:\n"
+"\n"
+"    * a point, while locked in workplane (rotate in plane, about that "
+"point)\n"
+"    * a point and a line or a normal (rotate about an axis through the "
+"point, and parallel to line / normal)\n"
+msgstr ""
+"Yeni dairesel kopyalama/çoğaltma oluşturmak için hatalı seçim. Bu grup "
+"şunlarla oluşturulabilir:\n"
+"\n"
+"    * bir nokta, çalışma düzleminde kilitli olduğu sürece (düzlemde o nokta "
+"etrafında çevirin)\n"
+"    * bir nokta ve bir çizgi veya bir normal ( çizgiye / normale paralel ve "
+"noktadan geçen bir eksen etrafında çevirin)\n"
+
+#: group.cpp:283
+msgctxt "group-name"
+msgid "rotate"
+msgstr "dairesel kopya"
+
+#: group.cpp:294
+msgctxt "group-name"
+msgid "translate"
+msgstr "doğrusal kopya"
+
+#: group.cpp:416
+msgid "(unnamed)"
+msgstr "(isimsiz)"
+
+#: groupmesh.cpp:707
+msgid "not closed contour, or not all same style!"
+msgstr "kapali olmayan kontur veya tümü ayni bicimde degil!"
+
+#: groupmesh.cpp:720
+msgid "points not all coplanar!"
+msgstr "noktaların hepsi aynı düzlemde değil!"
+
+#: groupmesh.cpp:722
+msgid "contour is self-intersecting!"
+msgstr "kontur kendisiyle kesisiyor!"
+
+#: groupmesh.cpp:724
+msgid "zero-length edge!"
+msgstr "sıfır-uzunluklu kenar!"
+
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr "Metin-biçimli STL dosyaları şu anda desteklenmiyor"
+
+#: modify.cpp:252
+msgid "Must be sketching in workplane to create tangent arc."
+msgstr "Teğet yay oluşturmak için çalışma düzleminde çizim yapılmalıdır."
+
+#: modify.cpp:299
+msgid ""
+"To create a tangent arc, select a point where two non-construction lines or "
+"circles in this group and workplane join."
+msgstr ""
+"Bir teğet yay oluşturmak için, bu gruptaki iki (yardımcı) referans-olmayan "
+"çizginin veya dairenin ve çalışma düzleminin birleştiği bir nokta seçin."
+
+#: modify.cpp:386
+msgid ""
+"Couldn't round this corner. Try a smaller radius, or try creating the "
+"desired geometry by hand with tangency constraints."
+msgstr ""
+"Bu köşe yuvarlatılamadı. Daha küçük bir yarıçap deneyin veya teğet "
+"kısıtlamaları ile istenen geometriyi elle oluşturmayı deneyin."
+
+#: modify.cpp:595
+msgid "Couldn't split this entity; lines, circles, or cubics only."
+msgstr ""
+"Bu öğe bölünemedi; yalnızca çizgiler, daireler veya kübik eğriler "
+"bölünebilir."
+
+#: modify.cpp:622
+msgid "Must be sketching in workplane to split."
+msgstr "Bölmek için çalışma düzleminde çizim yapılıyor olmalı."
+
+#: modify.cpp:629
+msgid ""
+"Select two entities that intersect each other (e.g. two lines/circles/arcs "
+"or a line/circle/arc and a point)."
+msgstr ""
+"Birbiriyle kesişen iki öğe seçin (örneğin iki çizgi / daire / yay veya bir "
+"çizgi / daire / yay ve bir nokta)."
+
+#: modify.cpp:734
+msgid "Can't split; no intersection found."
+msgstr "Bölünemez; kesişim bulunamadı."
+
+#: mouse.cpp:557
+msgid "Assign to Style"
+msgstr "Biçim Ata"
+
+#: mouse.cpp:573
+msgid "No Style"
+msgstr "Biçim Yok"
+
+#: mouse.cpp:576
+msgid "Newly Created Custom Style..."
+msgstr "Yeni Oluşturulan Özel Biçim ..."
+
+#: mouse.cpp:583
+msgid "Group Info"
+msgstr "Grup Bilgisi"
+
+#: mouse.cpp:603
+msgid "Style Info"
+msgstr "Biçim Bİlgisi"
+
+#: mouse.cpp:623
+msgid "Select Edge Chain"
+msgstr "Kenar Zinciri Seç"
+
+#: mouse.cpp:629
+msgid "Toggle Reference Dimension"
+msgstr "Referans Ölçüyü Değiştir"
+
+#: mouse.cpp:635
+msgid "Other Supplementary Angle"
+msgstr "Diğer Bütünler Açı"
+
+#: mouse.cpp:640
+msgid "Snap to Grid"
+msgstr "Izgaraya Tuttur"
+
+#: mouse.cpp:649
+msgid "Remove Spline Point"
+msgstr "Eğri Noktasını Sil"
+
+#: mouse.cpp:684
+msgid "Add Spline Point"
+msgstr "Eğri Noktası Ekle"
+
+#: mouse.cpp:688
+msgid "Cannot add spline point: maximum number of points reached."
+msgstr "Eğri noktası eklenemiyor: en fazla nokta sayısına ulaşıldı."
+
+#: mouse.cpp:713
+msgid "Toggle Construction"
+msgstr "Yapıyı değiştir"
+
+#: mouse.cpp:729
+msgid "Delete Point-Coincident Constraint"
+msgstr "Çakışık-Nokta Kısıtlamasını Sil"
+
+#: mouse.cpp:747
+msgid "Cut"
+msgstr "Kes"
+
+#: mouse.cpp:749
+msgid "Copy"
+msgstr "Kopyala"
+
+#: mouse.cpp:753
+msgid "Select All"
+msgstr "Tümünü Seç"
+
+#: mouse.cpp:758
+msgid "Paste"
+msgstr "Yapıştır"
+
+#: mouse.cpp:760
+msgid "Paste Transformed..."
+msgstr "Dönüştürerek Yapıştır..."
+
+#: mouse.cpp:765
+msgid "Delete"
+msgstr "Sil"
+
+#: mouse.cpp:768
+msgid "Unselect All"
+msgstr "Tüm Seçimi Kaldır"
+
+#: mouse.cpp:775
+msgid "Unselect Hovered"
+msgstr "Üzerine Gelinen Seçimi Kaldır"
+
+#: mouse.cpp:784
+msgid "Zoom to Fit"
+msgstr "Sığdırmak için Yakınlaştır"
+
+#: mouse.cpp:986 mouse.cpp:1274
+msgid "click next point of line, or press Esc"
+msgstr "çizginin sonraki noktası için tıklayın veya Esc tuşuna basın"
+
+#: mouse.cpp:992
+msgid ""
+"Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"3d'de dikdörtgen çizilemez; önce Çizim -> Çalışma Düzleminde menüsü ile bir "
+"çalışma düzlemini etkinleştirin."
+
+#: mouse.cpp:1026
+msgid "click to place other corner of rectangle"
+msgstr "dikdörtgenin diğer köşesini belirtmek için tıklayın"
+
+#: mouse.cpp:1047
+msgid "click to set radius"
+msgstr "yarıçapı ayarlamak için tıklayın"
+
+#: mouse.cpp:1052
+msgid ""
+"Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"3d'de yay çizemez; önce Çizim -> Çalışma Düzleminde menüsü ile bir çalışma "
+"düzlemini etkinleştirin."
+
+#: mouse.cpp:1071
+msgid "click to place point"
+msgstr "noktayı yerleştirmek için tıklayın"
+
+#: mouse.cpp:1087
+msgid "click next point of cubic, or press Esc"
+msgstr "sonraki kübik eğri noktasını tıklayın veya Esc tuşuna basın"
+
+#: mouse.cpp:1092
+msgid ""
+"Sketching in a workplane already; sketch in 3d before creating new workplane."
+msgstr ""
+"Zaten bir çalışma düzleminde çizim yapılıyor; 3d'de çizim yapmadan önce yeni "
+"çalışma düzlemi oluşturun."
+
+#: mouse.cpp:1108
+msgid ""
+"Can't draw text in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"3d'de metin yazılamaz; önce Çizim -> Çalışma Düzleminde menüsü ile bir "
+"çalışma düzlemini etkinleştirin."
+
+#: mouse.cpp:1125
+msgid "click to place bottom right of text"
+msgstr "metnin sağ alt konumunu belirtmek için tıklayın"
+
+#: mouse.cpp:1131
+msgid ""
+"Can't draw image in 3d; first, activate a workplane with Sketch -> In "
+"Workplane."
+msgstr ""
+"3d'de görüntü/resim eklenemez; önce Çizim -> Çalışma Düzleminde menüsü ile "
+"bir çalışma düzlemini etkinleştirin."
+
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
+msgctxt "file-type"
+msgid "SolveSpace models"
+msgstr "SolveSpace Modelleri"
+
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr "TÜMÜ"
+
+#: platform/gui.cpp:91
+msgctxt "file-type"
+msgid "IDF circuit board"
+msgstr "IDF devre kartı"
+
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr "STL üçgensel mesh (ağ/kafes)"
+
+#: platform/gui.cpp:96
+msgctxt "file-type"
+msgid "PNG image"
+msgstr "PNG Görüntüsü"
+
+#: platform/gui.cpp:100
+msgctxt "file-type"
+msgid "STL mesh"
+msgstr "STL mesh (ağ/kafes)"
+
+#: platform/gui.cpp:101
+msgctxt "file-type"
+msgid "Wavefront OBJ mesh"
+msgstr "Wavefront OBJ mesh (ağ/kafes)"
+
+#: platform/gui.cpp:102
+msgctxt "file-type"
+msgid "Three.js-compatible mesh, with viewer"
+msgstr "Görüntüleyicili, Three.js-uyumlu mesh (ağ/kafes)"
+
+#: platform/gui.cpp:103
+msgctxt "file-type"
+msgid "Three.js-compatible mesh, mesh only"
+msgstr "Three.js-uyumlu mesh, sadece mesh (ağ/kafes)"
+
+#: platform/gui.cpp:104
+msgctxt "file-type"
+msgid "VRML text file"
+msgstr "VRML metin dosyası"
+
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
+msgctxt "file-type"
+msgid "STEP file"
+msgstr "STEP dosyası"
+
+#: platform/gui.cpp:112
+msgctxt "file-type"
+msgid "PDF file"
+msgstr "PDF dosyası"
+
+#: platform/gui.cpp:113
+msgctxt "file-type"
+msgid "Encapsulated PostScript"
+msgstr "Encapsulated PostScript (EPS)"
+
+#: platform/gui.cpp:114
+msgctxt "file-type"
+msgid "Scalable Vector Graphics"
+msgstr "Ölçeklenebilir Vektör Grafikleri (SVG)"
+
+#: platform/gui.cpp:116 platform/gui.cpp:123
+msgctxt "file-type"
+msgid "DXF file (AutoCAD 2007)"
+msgstr "DXF dosyası (AutoCAD 2007)"
+
+#: platform/gui.cpp:117
+msgctxt "file-type"
+msgid "HPGL file"
+msgstr "HPGL dosyası"
+
+#: platform/gui.cpp:118
+msgctxt "file-type"
+msgid "G Code"
+msgstr "G Kodu"
+
+#: platform/gui.cpp:127
+msgctxt "file-type"
+msgid "AutoCAD DXF and DWG files"
+msgstr "AutoCAD DXF ve DWG dosyaları"
+
+#: platform/gui.cpp:131
+msgctxt "file-type"
+msgid "Comma-separated values"
+msgstr "Virgülle ayrılmış değerler (CSV)"
+
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
+msgid "untitled"
+msgstr "isimsiz"
+
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
+msgctxt "title"
+msgid "Save File"
+msgstr "Dosyayı Kaydet"
+
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
+msgctxt "title"
+msgid "Open File"
+msgstr "Dosyayı Aç"
+
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
+msgctxt "button"
+msgid "_Cancel"
+msgstr "_İptal"
+
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
+msgctxt "button"
+msgid "_Save"
+msgstr "_Kaydet"
+
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
+msgctxt "button"
+msgid "_Open"
+msgstr "_Aç"
+
+#: solvespace.cpp:171
+msgctxt "title"
+msgid "Autosave Available"
+msgstr "Otomatik Kaydetme Kullanılabilir"
+
+#: solvespace.cpp:172
+msgctxt "dialog"
+msgid "An autosave file is available for this sketch."
+msgstr "Bu çizim için otomatik kaydetme dosyası kullanılabilir."
+
+#: solvespace.cpp:173
+msgctxt "dialog"
+msgid "Do you want to load the autosave file instead?"
+msgstr "Bunun yerine otomatik kaydetme dosyasını yüklemek istiyor musunuz?"
+
+#: solvespace.cpp:174
+msgctxt "button"
+msgid "&Load autosave"
+msgstr "&Otomatik kaydı yükle"
+
+#: solvespace.cpp:176
+msgctxt "button"
+msgid "Do&n't Load"
+msgstr "&Yükleme"
+
+#: solvespace.cpp:599
+msgctxt "title"
+msgid "Modified File"
+msgstr "Değiştirilen Dosya"
+
+#: solvespace.cpp:601
+#, c-format
+msgctxt "dialog"
+msgid "Do you want to save the changes you made to the sketch “%s”?"
+msgstr "\"%s\" çiziminde yaptığınız değişiklikleri kaydetmek istiyor musunuz?"
+
+#: solvespace.cpp:604
+msgctxt "dialog"
+msgid "Do you want to save the changes you made to the new sketch?"
+msgstr "Yeni çizimde yaptığınız değişiklikleri kaydetmek istiyor musunuz?"
+
+#: solvespace.cpp:607
+msgctxt "dialog"
+msgid "Your changes will be lost if you don't save them."
+msgstr "Bunları kaydetmezseniz değişiklikleriniz kaybolur."
+
+#: solvespace.cpp:608
+msgctxt "button"
+msgid "&Save"
+msgstr "&Kaydet"
+
+#: solvespace.cpp:610
+msgctxt "button"
+msgid "Do&n't Save"
+msgstr "K&aydetme"
+
+#: solvespace.cpp:631
+msgctxt "title"
+msgid "(new sketch)"
+msgstr "(yeni çizim)"
+
+#: solvespace.cpp:638
+msgctxt "title"
+msgid "Property Browser"
+msgstr "Özellik Penceresi"
+
+#: solvespace.cpp:700
+msgid ""
+"Constraints are currently shown, and will be exported in the toolpath. This "
+"is probably not what you want; hide them by clicking the link at the top of "
+"the text window."
+msgstr ""
+"Kısıtlamalar şu anda gösterilmektedir ve takım yolunda dışa aktarılacaktır. "
+"Muhtemelen istediğiniz bu değil; Özellik Penceresinin üst kısmındaki "
+"bağlantıya tıklayarak bunları gizleyin."
+
+#: solvespace.cpp:772
+#, c-format
+msgid ""
+"Can't identify file type from file extension of filename '%s'; try .dxf or ."
+"dwg."
+msgstr ""
+"'%s' dosya adının dosya uzantısından dosya türü belirlenemiyor; .dxf veya ."
+"dwg'yi deneyin."
+
+#: solvespace.cpp:824
+msgid "Constraint must have a label, and must not be a reference dimension."
+msgstr "Kısıtlamanın bir etiketi olmalı ve bir referans ölçüsü olmamalıdır."
+
+#: solvespace.cpp:828
+msgid "Bad selection for step dimension; select a constraint."
+msgstr "Adım ölçüsü ayarlamak için hatalı seçim; bir kısıtlama seçin."
+
+#: solvespace.cpp:852
+msgid "The assembly does not interfere, good."
+msgstr "Montajda engel oluşturan parça yok, iyi."
+
+#: solvespace.cpp:868
+#, c-format
+msgid ""
+"The volume of the solid model is:\n"
+"\n"
+"    %s"
+msgstr ""
+"Katı modelin hacmi:\n"
+"\n"
+"    % s"
+
+#: solvespace.cpp:877
+#, c-format
+msgid ""
+"\n"
+"The volume of current group mesh is:\n"
+"\n"
+"    %s"
+msgstr ""
+"\n"
+"Mevcut ağ (kafes) grubunun hacmi:\n"
+"\n"
+"    %s"
+
+#: solvespace.cpp:882
+msgid ""
+"\n"
+"\n"
+"Curved surfaces have been approximated as triangles.\n"
+"This introduces error, typically of around 1%."
+msgstr ""
+"\n"
+"\n"
+"Kavisli (Eğri) yüzeyler üçgenler olarak yaklaştırılmıştır.\n"
+"Bu, genel olarak yaklaşık 1% hataya neden olur."
+
+#: solvespace.cpp:897
+#, c-format
+msgid ""
+"The surface area of the selected faces is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"Seçili yüzlerin yüzey alanı:\n"
+"\n"
+"    %s\n"
+"\n"
+"Eğriler, doğrusal parçalı olarak yaklaştırılmıştır.\n"
+"Bu, genel olarak yaklaşık 1%% hataya neden olur."
+
+#: solvespace.cpp:906
+msgid ""
+"This group does not contain a correctly-formed 2d closed area. It is open, "
+"not coplanar, or self-intersecting."
+msgstr ""
+"Bu grup, doğru biçimlendirilmiş 2d kapalı alan içermiyor. Açık, eş-düzlemli "
+"değil veya kendisiyle kesişiyor."
+
+#: solvespace.cpp:918
+#, c-format
+msgid ""
+"The area of the region sketched in this group is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"Bu grupta çizilen bölgenin alanı:\n"
+"\n"
+"    %s\n"
+"\n"
+"Eğriler, doğrusal parçalı olarak yaklaştırılmıştır.\n"
+"Bu, genel olarak yaklaşık 1%% hataya neden olur."
+
+#: solvespace.cpp:938
+#, c-format
+msgid ""
+"The total length of the selected entities is:\n"
+"\n"
+"    %s\n"
+"\n"
+"Curves have been approximated as piecewise linear.\n"
+"This introduces error, typically of around 1%%."
+msgstr ""
+"Seçilen öğelerin toplam uzunluğu:\n"
+"\n"
+"    %s\n"
+"\n"
+"Eğriler, parçalı doğrusal olarak yaklaştırıldı.\n"
+"Bu, genel olarak yaklaşık 1%% hataya neden olur."
+
+#: solvespace.cpp:944
+msgid "Bad selection for perimeter; select line segments, arcs, and curves."
+msgstr ""
+"Çevre uzunluğunu hesabı için hatalı seçim; çizgi parçalarını, yayları ve "
+"eğrileri seçin."
+
+#: solvespace.cpp:960
+msgid "Bad selection for trace; select a single point."
+msgstr "Nokta izleme işlemi için hatalı seçim; tek bir nokta seçin."
+
+#: solvespace.cpp:987
+#, c-format
+msgid "Couldn't write to '%s'"
+msgstr "\"%s\" öğesine yazılamadı"
+
+#: solvespace.cpp:1017
+msgid "The mesh is self-intersecting (NOT okay, invalid)."
+msgstr "Ağ (Kafes) kendisiyle kesişiyor (İyi DEĞİL, geçersiz)."
+
+#: solvespace.cpp:1018
+msgid "The mesh is not self-intersecting (okay, valid)."
+msgstr "Ağ (Kafes) kendisi ile kesişmiyor (iyi, geçerli)."
+
+#: solvespace.cpp:1020
+msgid "The mesh has naked edges (NOT okay, invalid)."
+msgstr "Ağın (Kafesin) açık kenarları var (iyi DEĞİL, geçersiz)."
+
+#: solvespace.cpp:1021
+msgid "The mesh is watertight (okay, valid)."
+msgstr "Ağ (Kafes) çok sıkı (iyi, geçerli)"
+
+#: solvespace.cpp:1024
+#, c-format
+msgid ""
+"\n"
+"\n"
+"The model contains %d triangles, from %d surfaces."
+msgstr ""
+"\n"
+"\n"
+"Model, %d yüzeyden %d üçgen içeriyor."
+
+#: solvespace.cpp:1028
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Zero problematic edges, good.%s"
+msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Sıfır sorunlu kenar, iyi.%s"
+
+#: solvespace.cpp:1031
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d problematic edges, bad.%s"
+msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d sorunlu kenar, kötü.%s"
+
+#: solvespace.cpp:1044
+#, c-format
+msgid ""
+"This is SolveSpace version %s.\n"
+"\n"
+"For more information, see http://solvespace.com/\n"
+"\n"
+"SolveSpace is free software: you are free to modify\n"
+"and/or redistribute it under the terms of the GNU\n"
+"General Public License (GPL) version 3 or later.\n"
+"\n"
+"There is NO WARRANTY, to the extent permitted by\n"
+"law. For details, visit http://gnu.org/licenses/\n"
+"\n"
+"© 2008-%d Jonathan Westhues and other authors.\n"
+msgstr ""
+"Bu SolveSpace'in %s sürümüdür.\n"
+"\n"
+"Daha fazla bilgi için bkz., http://solvespace.com/\n"
+"\n"
+"SolveSpace ücretsiz bir yazılımdır: GNU Genel Kamu \n"
+"Lisansı (GPL) sürüm 3 veya daha sonraki hükümleri altında \n"
+"onu değiştirmekte ve / veya yeniden dağıtmakta özgürsünüz.\n"
+"\n"
+"Yasaların izin verdiği ölçüde GARANTİ YOKTUR. \n"
+"Ayrıntılar için http://gnu.org/licenses/ adresini ziyaret edin.\n"
+"\n"
+"© 2008-% d Jonathan Westhues ve diğer yazarlar.\n"
+
+#: style.cpp:185
+msgid ""
+"Can't assign style to an entity that's derived from another entity; try "
+"assigning a style to this entity's parent."
+msgstr ""
+"Başka bir öğeden türetilen bir öğeye biçim atayamazsınız; bu öğenin üst "
+"öğesine bir biçim atamayı deneyin."
+
+#: style.cpp:735
+msgid "Style name cannot be empty"
+msgstr "Biçim adı boş olamaz"
+
+#: textscreens.cpp:791
+msgid "Can't repeat fewer than 1 time."
+msgstr "1 defadan az tekrarlanamaz."
+
+#: textscreens.cpp:795
+msgid "Can't repeat more than 999 times."
+msgstr "999 defadan fazla tekrarlanamaz."
+
+#: textscreens.cpp:820
+msgid "Group name cannot be empty"
+msgstr "Grup adı boş olamaz"
+
+#: textscreens.cpp:872
+msgid "Opacity must be between zero and one."
+msgstr "Şeffaflık değeri sıfır ile bir arasında olmalıdır."
+
+#: textscreens.cpp:907
+msgid "Radius cannot be zero or negative."
+msgstr "Yarıçap sıfır veya negatif değer olamaz."
+
+#: toolbar.cpp:18
+msgid "Sketch line segment"
+msgstr "Çizgi parçası çiz"
+
+#: toolbar.cpp:20
+msgid "Sketch rectangle"
+msgstr "Dikdörtgen çiz"
+
+#: toolbar.cpp:22
+msgid "Sketch circle"
+msgstr "Daire çiz"
+
+#: toolbar.cpp:24
+msgid "Sketch arc of a circle"
+msgstr "Bir çember yayı çiz"
+
+#: toolbar.cpp:26
+msgid "Sketch curves from text in a TrueType font"
+msgstr "TrueType yazı tipindeki metinden eğriler çiz"
+
+#: toolbar.cpp:28
+msgid "Sketch image from a file"
+msgstr "Bir dosyadan görüntü (resim) ekle"
+
+#: toolbar.cpp:30
+msgid "Create tangent arc at selected point"
+msgstr "Seçilen noktada radyus (teğet yay) oluştur"
+
+#: toolbar.cpp:32
+msgid "Sketch cubic Bezier spline"
+msgstr "Kübik Bezier Eğri Çiz"
+
+#: toolbar.cpp:34
+msgid "Sketch datum point"
+msgstr "Referans Nokta Ekle"
+
+#: toolbar.cpp:36
+msgid "Toggle construction"
+msgstr "Yapıyı değiştir"
+
+#: toolbar.cpp:38
+msgid "Split lines / curves where they intersect"
+msgstr "Çizgileri / eğrileri kesiştikleri yerden böl"
+
+#: toolbar.cpp:42
+msgid "Constrain distance / diameter / length"
+msgstr "Mesafeyi / çapı / uzunluğu kısıtla"
+
+#: toolbar.cpp:44
+msgid "Constrain angle"
+msgstr "Açıyı kısıtla"
+
+#: toolbar.cpp:46
+msgid "Constrain to be horizontal"
+msgstr "Yatay olarak kısıtla"
+
+#: toolbar.cpp:48
+msgid "Constrain to be vertical"
+msgstr "Dikey olarak kısıtla"
+
+#: toolbar.cpp:50
+msgid "Constrain to be parallel or tangent"
+msgstr "Paralel veya teğet olarak kısıtla"
+
+#: toolbar.cpp:52
+msgid "Constrain to be perpendicular"
+msgstr "Dik olarak kısıtla"
+
+#: toolbar.cpp:54
+msgid "Constrain point on line / curve / plane / point"
+msgstr "Noktayı çizgi / eğri / düzlem / nokta ile çakıştırarak kısıtla"
+
+#: toolbar.cpp:56
+msgid "Constrain symmetric"
+msgstr "Simetrik olarak kısıtla"
+
+#: toolbar.cpp:58
+msgid "Constrain equal length / radius / angle"
+msgstr "Eşit uzunluk / yarıçap / açı olarak kısıtla"
+
+#: toolbar.cpp:60
+msgid "Constrain normals in same orientation"
+msgstr "Normalleri aynı yönde kısıtla"
+
+#: toolbar.cpp:62
+msgid "Other supplementary angle"
+msgstr "Diğer bütünler açı"
+
+#: toolbar.cpp:64
+msgid "Toggle reference dimension"
+msgstr "Ölçüyü Referans Yap / Yapma"
+
+#: toolbar.cpp:68
+msgid "New group extruding active sketch"
+msgstr "Etkin çizimi uzatıp katılayarak yeni grup oluştur"
+
+#: toolbar.cpp:70
+msgid "New group rotating active sketch"
+msgstr "Etkin çizimi tam döndürerek yeni grup oluştur"
+
+#: toolbar.cpp:72
+msgid "New group helix from active sketch"
+msgstr "Etkin çizimden sarmal yeni grup oluştur"
+
+#: toolbar.cpp:74
+msgid "New group revolve active sketch"
+msgstr "Etkin çizimi kısmen döndürerek yeni grup oluştur"
+
+#: toolbar.cpp:76
+msgid "New group step and repeat rotating"
+msgstr "Adım ve tekrar değeri belirterek dairesel kopya grubu oluştur"
+
+#: toolbar.cpp:78
+msgid "New group step and repeat translating"
+msgstr "Adım ve tekrar değeri belirterek yeni doğrusal kopyalama grup oluştur"
+
+#: toolbar.cpp:80
+msgid "New group in new workplane (thru given entities)"
+msgstr ""
+"Yeni çalışma düzleminde yeni grup oluştur (verilen öğeler aracılığıyla)"
+
+#: toolbar.cpp:82
+msgid "New group in 3d"
+msgstr "3d'de yeni grup oluştur"
+
+#: toolbar.cpp:84
+msgid "New group linking / assembling file"
+msgstr "Bağlantı / Montaj dosyası ile yeni grup oluştur"
+
+#: toolbar.cpp:88
+msgid "Nearest isometric view"
+msgstr "En yakın izometrik görünüm"
+
+#: toolbar.cpp:90
+msgid "Align view to active workplane"
+msgstr "Görünümü etkin çalışma düzlemine hizala"
+
+#: util.cpp:165
+msgctxt "title"
+msgid "Error"
+msgstr "Hata"
+
+#: util.cpp:165
+msgctxt "title"
+msgid "Message"
+msgstr "Mesaj"
+
+#: util.cpp:170
+msgctxt "button"
+msgid "&OK"
+msgstr "&Tamam"
+
+#: view.cpp:127
+msgid "Scale cannot be zero or negative."
+msgstr "Ölçek sıfır veya negatif olamaz."
+
+#: view.cpp:139 view.cpp:148
+msgid "Bad format: specify x, y, z"
+msgstr "Kötü biçim: x, y, z'yi belirtin"
+
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Uzunluk oranı sınırlandırması için hatalı seçim. Bu sınırlandırma şunlara "
+#~ "uygulanabilir:\n"
+#~ "\n"
+#~ "     * iki çizgi parçası\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "Uzunluk farkı sınırlandırması için hatalı seçim. Bu sınırlandırma şunlara "
+#~ "uygulanabilir:\n"
+#~ "\n"
+#~ "     * iki çizgi parçası\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "&Uzunluk Oranı"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "U&zunluk Farkı"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "Çalışma düzleminde yeni taslak çizmek için hatalı seçim. Bu grup şunlarla "
+#~ "oluşturulabilir:\n"
+#~ "\n"
+#~ "     * bir nokta (nokta boyunca, eksenleri koordine etmek için "
+#~ "ortogonal)\n"
+#~ "     * bir nokta ve iki çizgi parçası (noktadan, çizgilere paralel)\n"
+#~ "     * bir çalışma düzlemi (çalışma düzleminin kopyası)\n"
+
+#~ msgctxt "file-type"
+#~ msgid "Q3D Object file"
+#~ msgstr "Q3D Object file"
index 1f2a2101e246ec5b7464c6facbff7e68df409d83..ee4c8fb2102e5eed76b9db68bb3f475192ad5731 100644 (file)
 # Ukrainian translations for SolveSpace package.
 # Copyright (C) 2017 the SolveSpace authors
 # This file is distributed under the same license as the SolveSpace package.
-# AppSoft4 <appsoft@ua.fm>, 2017.
+# app4soft <appsoft@ua.fm>, 2021.
 msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
-"PO-Revision-Date: 2017-01-05 10:30+0000\n"
-"Last-Translator: appsoft@ua.fm\n"
-"Language-Team: OpenOrienteeringUkraine\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2021-04-14 01:42+0300\n"
+"Last-Translator: https://github.com/Symbian9\n"
+"Language-Team: app4soft\n"
 "Language: uk_UA\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.4.2\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
 "Activate one with Sketch -> In Workplane."
 msgstr ""
+"Вирізання, вставка та копіювання працює лише у площині.\n"
+"\n"
+"Активуйте одну через Креслення -> У площині."
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
-msgstr ""
+msgstr "Буфер обміну порожній; немає чого вставляти."
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
-msgstr ""
+msgstr "Кількість копій для вставки має бути не менше одної."
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
-msgstr ""
+msgstr "Масштаб не може бути нульовим."
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
-msgstr ""
+msgstr "Оберіть одну точку для визначення центру обертання."
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
-msgstr ""
+msgstr "Оберіть дві точки для визначення вектору розміщення."
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
 msgstr ""
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
+#, fuzzy
 msgid "Too many items to paste; split this into smaller pastes."
-msgstr ""
+msgstr "Забагато об'єктів для вставки; рзділіть копіювання на кілька етапів."
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
-msgstr ""
+msgstr "Немає активної площини."
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
-msgstr ""
+msgstr "Некоректний формат: визначте координати X, Y, Z"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
-msgstr ""
+msgstr "Некоректний формат: визначте колір як R, G, B"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
+#, fuzzy
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
 msgstr ""
+"Значення перспективи не матиме ефекту допоки не ввімкнено Вигляд -> "
+"Використовувати Перспективну проєкцію."
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
-msgstr ""
+msgstr "Визначте кількість десяткових знаків від 0 до %d."
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
-msgstr ""
+msgstr "Масштаб експорту не може бути нульовим!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
-msgstr ""
+msgstr "Радіус відступу різання не може бути від'ємним!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
-msgstr ""
+msgstr "Некоректне значення: інтервал автозбереження має бути додатнім"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
+#, fuzzy
 msgid "Bad format: specify interval in integral minutes"
-msgstr ""
+msgstr "Некоректний формат: визначте цілим числом інтервал у хвилинах"
 
 #: constraint.cpp:12
 msgctxt "constr-name"
 msgid "pts-coincident"
-msgstr ""
+msgstr "співпадіння-тчк"
 
 #: constraint.cpp:13
 msgctxt "constr-name"
 msgid "pt-pt-distance"
-msgstr ""
+msgstr "відстань-тчк-тчк"
 
 #: constraint.cpp:14
 msgctxt "constr-name"
 msgid "pt-line-distance"
-msgstr ""
+msgstr "відстань-тчк-лінія"
 
 #: constraint.cpp:15
 msgctxt "constr-name"
 msgid "pt-plane-distance"
-msgstr ""
+msgstr "відстань-тчк-площина"
 
 #: constraint.cpp:16
 msgctxt "constr-name"
 msgid "pt-face-distance"
-msgstr ""
+msgstr "відстань-тчк-грань"
 
 #: constraint.cpp:17
 msgctxt "constr-name"
 msgid "proj-pt-pt-distance"
-msgstr ""
+msgstr "проєційна-відстань-тчк-тчк"
 
 #: constraint.cpp:18
 msgctxt "constr-name"
 msgid "pt-in-plane"
-msgstr ""
+msgstr "тчк-у-площині"
 
 #: constraint.cpp:19
 msgctxt "constr-name"
 msgid "pt-on-line"
-msgstr ""
+msgstr "тчк-на-лінії"
 
 #: constraint.cpp:20
 msgctxt "constr-name"
 msgid "pt-on-face"
-msgstr ""
+msgstr "тчк-на-грані"
 
 #: constraint.cpp:21
 msgctxt "constr-name"
 msgid "eq-length"
-msgstr ""
+msgstr "рівні-довжини"
 
 #: constraint.cpp:22
 msgctxt "constr-name"
 msgid "eq-length-and-pt-ln-dist"
-msgstr ""
+msgstr "рівні-довжина-відстань-тчк-лінія"
 
 #: constraint.cpp:23
 msgctxt "constr-name"
 msgid "eq-pt-line-distances"
-msgstr ""
+msgstr "рівна-відстань-тчк-лінія"
 
 #: constraint.cpp:24
 msgctxt "constr-name"
 msgid "length-ratio"
-msgstr ""
+msgstr "пропорція-довжин"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
-msgid "length-difference"
+msgid "arc-arc-length-ratio"
 msgstr ""
 
 #: constraint.cpp:26
 msgctxt "constr-name"
-msgid "symmetric"
+msgid "arc-line-length-ratio"
 msgstr ""
 
 #: constraint.cpp:27
 msgctxt "constr-name"
-msgid "symmetric-h"
-msgstr ""
+msgid "length-difference"
+msgstr "різниця-довжин"
 
 #: constraint.cpp:28
 msgctxt "constr-name"
-msgid "symmetric-v"
+msgid "arc-arc-len-difference"
 msgstr ""
 
 #: constraint.cpp:29
 msgctxt "constr-name"
-msgid "symmetric-line"
+msgid "arc-line-len-difference"
 msgstr ""
 
 #: constraint.cpp:30
 msgctxt "constr-name"
-msgid "at-midpoint"
-msgstr ""
+msgid "symmetric"
+msgstr "симетрія"
 
 #: constraint.cpp:31
 msgctxt "constr-name"
-msgid "horizontal"
-msgstr ""
+msgid "symmetric-h"
+msgstr "симетрія-вертикально"
 
 #: constraint.cpp:32
 msgctxt "constr-name"
-msgid "vertical"
-msgstr ""
+msgid "symmetric-v"
+msgstr "симетрія-горизонтально"
 
 #: constraint.cpp:33
 msgctxt "constr-name"
-msgid "diameter"
-msgstr ""
+msgid "symmetric-line"
+msgstr "симетрія-відносно-лінії"
 
 #: constraint.cpp:34
 msgctxt "constr-name"
-msgid "pt-on-circle"
-msgstr ""
+msgid "at-midpoint"
+msgstr "на-середині"
 
 #: constraint.cpp:35
 msgctxt "constr-name"
-msgid "same-orientation"
-msgstr ""
+msgid "horizontal"
+msgstr "горизонталь"
 
 #: constraint.cpp:36
 msgctxt "constr-name"
-msgid "angle"
-msgstr ""
+msgid "vertical"
+msgstr "вертикаль"
 
 #: constraint.cpp:37
 msgctxt "constr-name"
-msgid "parallel"
-msgstr ""
+msgid "diameter"
+msgstr "діаметр"
 
 #: constraint.cpp:38
 msgctxt "constr-name"
-msgid "arc-line-tangent"
-msgstr ""
+msgid "pt-on-circle"
+msgstr "тчк-на-колі"
 
 #: constraint.cpp:39
 msgctxt "constr-name"
-msgid "cubic-line-tangent"
-msgstr ""
+msgid "same-orientation"
+msgstr "співнаправленість"
 
 #: constraint.cpp:40
 msgctxt "constr-name"
-msgid "curve-curve-tangent"
-msgstr ""
+msgid "angle"
+msgstr "кут"
 
 #: constraint.cpp:41
 msgctxt "constr-name"
-msgid "perpendicular"
-msgstr ""
+msgid "parallel"
+msgstr "паралель"
 
 #: constraint.cpp:42
 msgctxt "constr-name"
-msgid "eq-radius"
-msgstr ""
+msgid "arc-line-tangent"
+msgstr "дотичні-дуга-лінія"
 
 #: constraint.cpp:43
 msgctxt "constr-name"
-msgid "eq-angle"
-msgstr ""
+msgid "cubic-line-tangent"
+msgstr "дотичні-сплайн-лінія"
 
 #: constraint.cpp:44
 msgctxt "constr-name"
-msgid "eq-line-len-arc-len"
-msgstr ""
+msgid "curve-curve-tangent"
+msgstr "дотичні-крива-крива"
 
 #: constraint.cpp:45
 msgctxt "constr-name"
-msgid "lock-where-dragged"
-msgstr ""
+msgid "perpendicular"
+msgstr "перпендикуляр"
 
 #: constraint.cpp:46
 msgctxt "constr-name"
+msgid "eq-radius"
+msgstr "рівнозначні-радіуси"
+
+#: constraint.cpp:47
+msgctxt "constr-name"
+msgid "eq-angle"
+msgstr "рівнозначні-кути"
+
+#: constraint.cpp:48
+msgctxt "constr-name"
+msgid "eq-line-len-arc-len"
+msgstr "рівнозначні-лінія-дуга"
+
+#: constraint.cpp:49
+msgctxt "constr-name"
+msgid "lock-where-dragged"
+msgstr "фіксоване-положення"
+
+#: constraint.cpp:50
+msgctxt "constr-name"
 msgid "comment"
-msgstr ""
+msgstr "коментар"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
 msgstr ""
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
 msgstr ""
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
 msgstr ""
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -299,7 +328,7 @@ msgid ""
 "    * a circle or an arc (diameter)\n"
 msgstr ""
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -311,7 +340,7 @@ msgid ""
 "    * a point and a plane face (point on face)\n"
 msgstr ""
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -327,22 +356,26 @@ msgid ""
 "    * a line segment and an arc (line segment length equals arc length)\n"
 msgstr ""
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -350,7 +383,7 @@ msgid ""
 "    * a line segment and a workplane (line's midpoint on plane)\n"
 msgstr ""
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -362,19 +395,19 @@ msgid ""
 "workplane)\n"
 msgstr ""
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
 msgstr ""
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
 msgstr ""
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -383,7 +416,7 @@ msgid ""
 "    * a line segment\n"
 msgstr ""
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
@@ -391,15 +424,16 @@ msgid ""
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:614
+#: constraint.cpp:663
+#, fuzzy
 msgid "Must select an angle constraint."
-msgstr ""
+msgstr "Необхідно обрати кут."
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
-msgstr ""
+msgstr "Необхідно обрати обмежувач з відповідною міткою."
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -408,11 +442,11 @@ msgid ""
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr ""
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -423,7 +457,7 @@ msgid ""
 "    * two line segments, arcs, or beziers, that share an endpoint (tangent)\n"
 msgstr ""
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -432,7 +466,7 @@ msgid ""
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
@@ -440,15 +474,22 @@ msgid ""
 "    * a point\n"
 msgstr ""
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "КОМЕНТАР -- ДВІЧІ КЛІКНІТЬ ДЛЯ РЕДАГУВАННЯ"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
-msgstr ""
+msgstr "клікніть в місце де буде центр коментаря"
 
 #: export.cpp:19
 msgid ""
 "No solid model present; draw one with extrudes and revolves, or use Export "
 "2d View to export bare lines and curves."
 msgstr ""
+"Вісутня об'ємна модель; створіть одну з допомогою екструдування та "
+"виточування або скористайтеся функцією \"Експортувати 2D Вигляд\" для "
+"еспорту лише ліній та кривих."
 
 #: export.cpp:61
 msgid ""
@@ -460,56 +501,66 @@ msgid ""
 "lines)\n"
 msgstr ""
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
-msgstr ""
+msgstr "Активна група не містить меш; немає чого експортувати."
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr ""
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr ""
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
+"Деякі аспекти креслення на мають відповідників у форматі DXF і не будуть "
+"експортовані:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
+"Розмір аркуша у PDF перевищує 200×200 дюймів; багато переглядачів можуть не "
+"підтримувати цей файл."
 
 #: file.cpp:44 group.cpp:91
 msgctxt "group-name"
 msgid "sketch-in-plane"
-msgstr ""
+msgstr "креслення-в-площині"
 
 #: file.cpp:62
 msgctxt "group-name"
 msgid "#references"
-msgstr ""
+msgstr "#базові-площини"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr "Файл порожній. Він може бути пошкодженим."
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
 msgstr ""
+"Нерозпізнані дані у файлі. Цей файл може бути пошкодженим або збереженим "
+"новою версією програми."
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
-msgstr ""
+msgstr "Втрачений Файл"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
-msgstr ""
+msgstr "Приєднаний файл “%s” відсутній."
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -518,20 +569,20 @@ msgid ""
 "permanently removed."
 msgstr ""
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
-msgstr ""
+msgstr "&Так"
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
-msgstr ""
+msgstr "&Ні"
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
-msgstr ""
+msgstr "&Відмінити"
 
 #: graphicswin.cpp:41
 msgid "&File"
@@ -563,15 +614,15 @@ msgstr "Експортувати &Зображення..."
 
 #: graphicswin.cpp:49
 msgid "Export 2d &View..."
-msgstr "Експортувати 2d &Вигляд..."
+msgstr "Експортувати 2D &Вигляд..."
 
 #: graphicswin.cpp:50
 msgid "Export 2d &Section..."
-msgstr "Експортувати 2d &Секцію..."
+msgstr "Експортувати 2D &Секцію..."
 
 #: graphicswin.cpp:51
 msgid "Export 3d &Wireframe..."
-msgstr "Експортувати 3d &Скелет..."
+msgstr "Експортувати 3D &Скелет..."
 
 #: graphicswin.cpp:52
 msgid "Export Triangle &Mesh..."
@@ -631,7 +682,7 @@ msgstr "Вставити &Трансфмованим..."
 
 #: graphicswin.cpp:72
 msgid "&Delete"
-msgstr "&Delete"
+msgstr "&Видалити"
 
 #: graphicswin.cpp:74
 msgid "Select &Edge Chain"
@@ -647,19 +698,19 @@ msgstr "&Зняти Виділення з Усього"
 
 #: graphicswin.cpp:78
 msgid "&Line Styles..."
-msgstr ""
+msgstr "Стилі &Ліній..."
 
 #: graphicswin.cpp:79
 msgid "&View Projection..."
-msgstr ""
+msgstr "&Проекція Відображення..."
 
 #: graphicswin.cpp:81
 msgid "Con&figuration..."
-msgstr ""
+msgstr "&Налаштування..."
 
 #: graphicswin.cpp:84
 msgid "&View"
-msgstr "&View"
+msgstr "&Відображення"
 
 #: graphicswin.cpp:85
 msgid "Zoom &In"
@@ -687,7 +738,7 @@ msgstr "Найближчий &Ізометричний Вигляд"
 
 #: graphicswin.cpp:92
 msgid "&Center View At Point"
-msgstr "&ЦенÑ\82Ñ\80Ñ\83ваÑ\82и Ð\92иглÑ\8fд Ð\9dа Точці"
+msgstr "&ЦенÑ\82Ñ\80Ñ\83ваÑ\82и Ð\92иглÑ\8fд Ð½а Точці"
 
 #: graphicswin.cpp:94
 msgid "Show Snap &Grid"
@@ -695,302 +746,314 @@ msgstr "Показати &Сітку Прикріплення"
 
 #: graphicswin.cpp:95
 msgid "Darken Inactive Solids"
-msgstr ""
+msgstr "Затінювати Неактивні Тіла"
 
 #: graphicswin.cpp:96
 msgid "Use &Perspective Projection"
 msgstr "Використовувати &Перспективну Проекцію"
 
 #: graphicswin.cpp:97
-msgid "Dimension &Units"
+msgid "Show E&xploded View"
 msgstr ""
 
 #: graphicswin.cpp:98
-msgid "Dimensions in &Millimeters"
-msgstr "РозмÑ\96Ñ\80и Ð² &Ð\9cÑ\96лÑ\96меÑ\82Ñ\80аÑ\85"
+msgid "Dimension &Units"
+msgstr "РозмÑ\96Ñ\80нÑ\96 &Ð\9eдиниÑ\86Ñ\96"
 
 #: graphicswin.cpp:99
-msgid "Dimensions in M&eters"
-msgstr ""
+msgid "Dimensions in &Millimeters"
+msgstr "Розміри у &Міліметрах"
 
 #: graphicswin.cpp:100
+msgid "Dimensions in M&eters"
+msgstr "Розміри у &Метрах"
+
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
-msgstr "Розміри в &Дюймах"
+msgstr "Розміри у &Дюймах"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr ""
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "Показати Панель &Інструментів"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "Показати Вікно Власти&востей"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "&Повний Екран"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "&Нова Група"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
-msgstr "Креслення В &3d"
+msgstr "Креслення у &3D"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
-msgstr "Креслення В Новій Робочій &Площині"
+msgstr "Креслення у Новій &Площині"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "Покрокове &Переміщення"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "Покрокове &Обертання"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "Ви&давити"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
-msgstr ""
+msgstr "&Спіраль"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "&Виточити"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
-msgstr ""
+msgstr "&Обертати"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
-msgstr "Ð\9fÑ\80иÑ\94днаÑ\82и / Ð\9cонÑ\82Ñ\83вати..."
+msgstr "Ð\9fÑ\80иÑ\94днаÑ\82и / Ð\97Ñ\96бÑ\80ати..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
-msgstr "Приєднати Недавні"
+msgstr "Приєднати Нещодавні"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "&Креслення"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
-msgstr "Ð\92 Робочій &Площині"
+msgstr "У Робочій &Площині"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
-msgstr "Ð\91Ñ\83дÑ\8c-де Ð\92 &3d"
+msgstr "Ð\91Ñ\83дÑ\8c-де Ð² &3D"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "Опорна &Точка"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "Робоча &Площина"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "&Відрізок Прямої"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "Контсрук&ційний Відрізок Прямої"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "&Прямокутник"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "&Коло"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "&Дуга Кола"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "Кубічний Сплайн &Без'є"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
-msgstr "&Текст з TrueType Шрифтом"
+msgstr "&Текст із TrueType Шрифтом"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
-msgstr ""
+msgstr "&Зображення"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "Пере&мкнути Конструктивність"
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "Дотична &Дуга на Точці"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "Розрізати Криві на &Перетині"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "&Обмежити"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "&Відстань / Діаметр"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "Від&носний Розмір"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "К&ут"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "Відносний К&ут"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "Інший Су&міжний Кут"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "Перемкнути Від&носність Розмірів"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "&Горизонтально"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "&Вертикально"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "&На точці / Кривій / Площині"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "Рі&вні Довжина / Радіус / Кут"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "Про&порція Довжин"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr ""
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "Рі&зниця Довжин"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr ""
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "До &Середини"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "Си&метрично"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "Пара&лельно / Дотична"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "&Препендикулярно"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "Однакова Орієн&тація"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "Фіксувати Точку Після &Переміщення"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "Коментар"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "&Аналізувати"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "Обрахувати &Об'єм"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "Обрахувати Пл&ощу"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "Обрахувати &Периметр"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "Показати &Дотичні Частини"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "Показати &Приховані Ребра"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
-msgstr ""
+msgstr "Показати &Центр Масс"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
-msgstr ""
+msgstr "Показати &Надмірно Обмежені Точки"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "&Трасувати Точку"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr "&Зупити Трасування..."
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "Прорахувати &Розмір..."
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "&Довідка"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "&Мова"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "&Вебсайт / Посібник"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "&Про програму"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
-msgstr ""
+msgstr "(нємає нещодавніх файлів)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
-msgstr ""
+msgstr "Файл '%s' відсутній."
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
-msgstr ""
+msgstr "Відсутня активна площина - сітка не відображатиметься."
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -999,91 +1062,91 @@ msgid ""
 "configuration screen. A value around 0.3 is typical."
 msgstr ""
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr ""
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr ""
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
 msgstr ""
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
 msgstr ""
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
 msgstr ""
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
 "workplane group."
 msgstr ""
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
 msgstr ""
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr ""
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
-msgstr ""
+msgstr "клікніть для встановлення вихідної точки"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
-msgstr ""
+msgstr "клікніть першу точку прямої лінії"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
-msgstr ""
+msgstr "клікніть першу точку конструктивної прямої лінії"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
-msgstr ""
+msgstr "клікніть першу точку кривої"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
-msgstr ""
+msgstr "клікніть в місце де буде центр коментаря"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
-msgstr ""
+msgstr "клікніть в центр відліку площини"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
-msgstr ""
+msgstr "клікніть для встановлення першого кута прямокутника"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
-msgstr ""
+msgstr "клікніть для встановлення верхньої лівої межі тексту"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
-msgstr ""
+msgstr "клікніть для встановлення верхньої лівої межі зображення"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1092,34 +1155,37 @@ msgstr ""
 #: group.cpp:86
 msgctxt "group-name"
 msgid "sketch-in-3d"
-msgstr ""
+msgstr "ескіз-в-3D"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
 msgstr ""
+"Активуйте робочу площину ( Ескіз -> У Площині) перед екструдуванням. Ескіз "
+"буде екструдовано перпендикулярно до робочої площини."
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
-msgstr ""
+msgstr "видавлювання"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1128,16 +1194,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
-msgstr ""
+msgstr "проточування"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1146,16 +1212,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
-msgstr ""
+msgstr "прокручування"
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
-msgstr ""
+msgstr "Спіраль може бути створена лише на основі площинного ескізу."
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1164,12 +1230,12 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
-msgstr ""
+msgstr "спіраль"
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1179,436 +1245,451 @@ msgid ""
 "point, and parallel to line / normal)\n"
 msgstr ""
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
-msgstr ""
+msgstr "крутіння"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
-msgstr ""
+msgstr "перекладання"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
-msgstr ""
+msgstr "(безіменне)"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
-msgstr ""
+msgstr "не замкнений контур або не все в єдиному стилі!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr ""
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
-msgstr ""
+msgstr "контур самоперетинається!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
+msgstr "ребро нульової довжини!"
+
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
 msgstr ""
 
-#: modify.cpp:254
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr ""
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
 msgstr ""
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
 msgstr ""
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 
-#: modify.cpp:624
+#: modify.cpp:622
+#, fuzzy
 msgid "Must be sketching in workplane to split."
-msgstr ""
+msgstr "Має бути накреслений у робочій площині для розділеня."
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
 msgstr ""
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
-msgstr ""
+msgstr "Неможливо розділити; відсутній перетин."
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "Встановити Стиль"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "Без Стилю"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "Створити Користувацький Стиль..."
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "Параметри Групи"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "Параметри Стилю"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "Виділити Ланцюг Ребер"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "Перемкнути Відносність Розміру"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "Інший Суміжний Кут"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "Прикріпити до Сітки"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "Видалити Точку Сплайну"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "Додати Точку Сплайну"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr ""
+"Неможливо додати точку сплайна: перевищено максимальну кількість точок."
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "Пермкнути Конструктивність"
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "Роз'єднати З'єднання Точок"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "Вирізати"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "Копіювати"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "Виділити Усе"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "Вставити"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "Вставити Трансформованим..."
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "Видалити"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "Зняти Виділення з Усього"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "Зняти Виділення з Наведеного"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "Умістити на Екрані"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
-msgstr ""
+msgstr "клікніть наступну точку лінії або натисніть Esc"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr ""
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
-msgstr ""
+msgstr "клікніть для встановлення іншого кута прямокутника"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
-msgstr ""
+msgstr "клікніть для визначення радіусу"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr ""
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
-msgstr ""
+msgstr "клікніть для встановлення точки"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
-msgstr ""
+msgstr "клікніть наступну точку кривої або натисніть Esc"
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr ""
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
-msgstr ""
+msgstr "клікніть для встановлення нижньої правої межі тексту"
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr ""
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr ""
-
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
+msgstr "SolveSpace модель"
+
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
 msgstr ""
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
+msgstr "IDF друкована плата"
+
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
 msgstr ""
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
-msgstr ""
+msgstr "PNG зображення"
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
-msgstr ""
+msgstr "STL меш"
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
-msgstr ""
+msgstr "Wavefront OBJ меш"
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
-msgstr ""
+msgstr "Three.js-сумісний меш, з переглядачем"
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
-msgstr ""
+msgstr "Three.js-сумісний меш, лише меш"
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
-msgstr ""
+msgstr "VRML меш, текстовий формат"
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
-msgstr ""
+msgstr "STEP файл"
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
-msgstr ""
+msgstr "PDF файл"
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
-msgstr ""
+msgstr "Encapsulated PostScript"
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
-msgstr ""
+msgstr "Scalable Vector Graphics, векторний формат"
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
-msgstr ""
+msgstr "DXF файл (AutoCAD 2007)"
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
-msgstr ""
+msgstr "HPGL файл"
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
-msgstr ""
+msgstr "G Code"
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
-msgstr ""
+msgstr "AutoCAD DXF та DWG файли"
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
-msgstr ""
+msgstr "Comma-separated values"
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
-msgstr ""
+msgstr "без імені"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
-msgstr ""
+msgstr "Зберегти Файл"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
-msgstr ""
+msgstr "Відкрити Файл"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
-msgstr ""
+msgstr "_Скасувати"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
-msgstr ""
+msgstr "_Зберегти"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
-msgstr ""
+msgstr "_Відкрити"
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
-msgstr ""
+msgstr "Наявні автозбереження"
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
-msgstr ""
+msgstr "Наявні автозбереження для цього креслення."
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
-msgstr ""
+msgstr "Завантажити файл автозбереження?"
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
-msgstr ""
+msgstr "&Завантажити автозбереження"
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
-msgstr ""
+msgstr "&Не Завантажувати"
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
-msgstr ""
+msgstr "Файл Змінено"
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
-msgstr ""
+msgstr "Чи хочете ви зберегти зміни зроблені вами у ескізі “%s”?"
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
-msgstr ""
+msgstr "Чи хочете ви зберегти зміни зроблені вами у новому ескізі?"
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
-msgstr ""
+msgstr "Ваші зміни буде втрачено якщо ви не збережете їх."
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
-msgstr ""
+msgstr "&Зберегти"
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
-msgstr ""
+msgstr "&Не Зберігати"
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
-msgstr ""
+msgstr "(нове креслення)"
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
-msgstr ""
+msgstr "Браузер Властивостей"
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
 "the text window."
 msgstr ""
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
 "dwg."
 msgstr ""
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
-msgstr ""
+msgstr "Обмежувач має містити мітку і бути не відносним розміром."
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
-msgstr ""
+msgstr "Поганий вибір для крокової зміни розміру; оберіть обмежувач."
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr ""
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
 "\n"
 "    %s"
 msgstr ""
+"Об'єм твердого тіла становить:\n"
+"\n"
+"    %s"
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1616,8 +1697,12 @@ msgid ""
 "\n"
 "    %s"
 msgstr ""
+"\n"
+"Об'єм поточної групи мешу становить:\n"
+"\n"
+"    %s"
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1625,7 +1710,7 @@ msgid ""
 "This introduces error, typically of around 1%."
 msgstr ""
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1636,13 +1721,15 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
 msgstr ""
+"Ця група не місить коректно сформованого замкненої 2D площини. Вона "
+"відкрита, не компланарна, або ж самоперетинається."
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1652,8 +1739,14 @@ msgid ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 msgstr ""
+"Площа заповнення ескізу у цій групі становить:\n"
+"\n"
+"    %s\n"
+"\n"
+"Криві наближено до ламаних ліній.\n"
+"Це вносить похибку, зазвичай близько 1%%."
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1663,37 +1756,43 @@ msgid ""
 "Curves have been approximated as piecewise linear.\n"
 "This introduces error, typically of around 1%%."
 msgstr ""
+"Загальна довжина обраних елементів становить:\n"
+"\n"
+"    %s\n"
+"\n"
+"Криві наближено до ламаних ліній.\n"
+"Це вносить похибку, зазвичай близько 1%%."
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
-msgstr ""
+msgstr "Поганий вибір для периметру; оберіть відрізки, дуги та криві."
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
-msgstr ""
+msgstr "Поганий вибір для вістежування шляху; оберіть одну точку."
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
-msgstr ""
+msgstr "Неможливо записати у '%s'"
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
-msgstr ""
+msgstr "Меш самоперетинається (НЕ добре, недійсний)."
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
-msgstr ""
+msgstr "Меш самоперетинається (добре, дійсний)."
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
-msgstr ""
+msgstr "Меш містить оголені ребра (НЕ добре, недійсний)."
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
-msgstr ""
+msgstr "Меш водонепроникний (добре, дійсний)."
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1701,7 +1800,7 @@ msgid ""
 "The model contains %d triangles, from %d surfaces."
 msgstr ""
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1710,8 +1809,13 @@ msgid ""
 "\n"
 "Zero problematic edges, good.%s"
 msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"Відсутні проблемні ребра, добре.%s"
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1720,8 +1824,13 @@ msgid ""
 "\n"
 "%d problematic edges, bad.%s"
 msgstr ""
+"%s\n"
+"\n"
+"%s\n"
+"\n"
+"%d проблемних ребер, погано.%s"
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1737,36 +1846,50 @@ msgid ""
 "\n"
 "© 2008-%d Jonathan Westhues and other authors.\n"
 msgstr ""
+"Це SolveSpace версії %s.\n"
+"\n"
+"Більше інформації на сайті http://solvespace.com/\n"
+"\n"
+"SolveSpace є вільною програмою: ви можете модифікувати\n"
+"та/або розповсюджувати її відповідно до ліцензії GNU\n"
+"General Public License (GPL) версії 3 чи новішої.\n"
+"\n"
+"ВІЧСУТНІ БУДЬ-ЯКІ ГАРАНТІЇ, в межах, доволених\n"
+"законом. Деталі на сайті http://gnu.org/licenses/\n"
+"\n"
+"© 2008-%d Jonathan Westhues та інші автори.\n"
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
 msgstr ""
+"Неможливо призначити стиль елементу який походить від іншого елемента; "
+"спробуйте призначити стиль батьківському елементу."
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
-msgstr ""
+msgstr "Стиль не може містити порожнє ім'я"
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
-msgstr ""
+msgstr "Не можливо повторити менше 1 разу."
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
-msgstr ""
+msgstr "Не можливо повторити понад 999 разів."
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
-msgstr ""
+msgstr "Група не може містити порожнє ім'я"
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
-msgstr ""
+msgstr "Непрозорість має бути між 0 та 1."
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
-msgstr ""
+msgstr "Радіус не може бути нульовим чи від'ємним."
 
 #: toolbar.cpp:18
 msgid "Sketch line segment"
@@ -1790,7 +1913,7 @@ msgstr "Накреслити криві з тексту на TrueType шрифт
 
 #: toolbar.cpp:28
 msgid "Sketch image from a file"
-msgstr ""
+msgstr "Вставити зображення з файлу"
 
 #: toolbar.cpp:30
 msgid "Create tangent arc at selected point"
@@ -1862,19 +1985,19 @@ msgstr "Перемкнути відносність розміру"
 
 #: toolbar.cpp:68
 msgid "New group extruding active sketch"
-msgstr "Ð\9dова Ð³Ñ\80Ñ\83па ÐµÐºÑ\81Ñ\82Ñ\80Ñ\83дÑ\83ваннÑ\8f Ð°ÐºÑ\82ивного ÐºÑ\80еÑ\81леннÑ\8f"
+msgstr "Ð\9dова Ð³Ñ\80Ñ\83па ÐµÐºÑ\81Ñ\82Ñ\80Ñ\83дÑ\83ваннÑ\8f Ð°ÐºÑ\82ивного ÐµÑ\81кÑ\96зÑ\83"
 
 #: toolbar.cpp:70
 msgid "New group rotating active sketch"
-msgstr "Ð\9dова Ð³Ñ\80Ñ\83па Ð¾Ð±ÐµÑ\80Ñ\82аннÑ\8f Ð°ÐºÑ\82иного ÐºÑ\80еÑ\81леннÑ\8f"
+msgstr "Ð\9dова Ð³Ñ\80Ñ\83па Ð¾Ð±ÐµÑ\80Ñ\82аннÑ\8f Ð°ÐºÑ\82иного ÐµÑ\81кÑ\96зÑ\83"
 
 #: toolbar.cpp:72
 msgid "New group helix from active sketch"
-msgstr ""
+msgstr "Нова група спіралі з активного ескізу"
 
 #: toolbar.cpp:74
 msgid "New group revolve active sketch"
-msgstr ""
+msgstr "Нова група обертання активного ескізу"
 
 #: toolbar.cpp:76
 msgid "New group step and repeat rotating"
@@ -1890,7 +2013,7 @@ msgstr "Нова група в новій площині (через обран
 
 #: toolbar.cpp:82
 msgid "New group in 3d"
-msgstr "Нова група в 3d"
+msgstr "Нова група в 3D"
 
 #: toolbar.cpp:84
 msgid "New group linking / assembling file"
@@ -1907,25 +2030,31 @@ msgstr "Вирівняти вигляд до активної робочої п
 #: util.cpp:165
 msgctxt "title"
 msgid "Error"
-msgstr ""
+msgstr "Помилка"
 
 #: util.cpp:165
 msgctxt "title"
 msgid "Message"
-msgstr ""
+msgstr "Повідомлення"
 
 #: util.cpp:170
 msgctxt "button"
 msgid "&OK"
-msgstr ""
+msgstr "&OK"
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
-msgstr ""
+msgstr "Масштаб не може бути нульовим чи від'ємним."
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
-msgstr ""
+msgstr "Некоректний формат: визначте X, Y, Z"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "Про&порція Довжин"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "Рі&зниця Довжин"
 
 #~ msgid "Show Degrees of &Freedom"
 #~ msgstr "Показати Степені &Свободи"
index 245b452a0aebf6e61ab7bd8937be4a989797d829..5cbf6997e50daff8f02458726bafebdc9ee0204a 100644 (file)
@@ -7,17 +7,17 @@ msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
-"PO-Revision-Date: 2020-09-28 12:42+0800\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
+"PO-Revision-Date: 2021-04-03 13:10-0400\n"
 "Last-Translator: lomatus@163.com\n"
 "Language-Team: none\n"
 "Language: zh_CN\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.4.1\n"
+"X-Generator: Poedit 2.4.2\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
@@ -27,72 +27,72 @@ msgstr ""
 "\n"
 "使用\"工作平面中的草图 -+\"激活一个。"
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr "剪贴板为空;没有要粘贴的内容。"
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr "要粘贴的副本数必须至少为 1 个。"
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr "缩放不能为零。"
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr "选择一个点以定义旋转原点。"
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr "选择两个点来定义转换向量。"
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid ""
 "Transformation is identity. So all copies will be exactly on top of each "
 "other."
 msgstr "转换就是标识,因此所有的复制在彼此之上。"
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr "要粘贴的项目太多; 请把他们拆分。"
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr "没有工作平面处于活动状态。"
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr "格式错误:将坐标指定为 x、y、z"
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr "格式错误:将颜色指定为 r、g、b"
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use "
 "Perspective Projection."
 msgstr "在启用\"视图 -= 使用透视投影\"之前,透视因子将不起作用。"
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr "在十进制之后指定 0 和 %d 数字之间。"
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr "输出比例不能为零!"
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr "刀具半径偏移不能为负数!"
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr "坏值:自动保存间隔应为正"
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr "格式错误:以整数分钟为单位指定间隔"
 
@@ -163,134 +163,154 @@ msgstr "长度比率"
 
 #: constraint.cpp:25
 msgctxt "constr-name"
+msgid "arc-arc-length-ratio"
+msgstr ""
+
+#: constraint.cpp:26
+msgctxt "constr-name"
+msgid "arc-line-length-ratio"
+msgstr ""
+
+#: constraint.cpp:27
+msgctxt "constr-name"
 msgid "length-difference"
 msgstr "长度不同"
 
-#: constraint.cpp:26
+#: constraint.cpp:28
+msgctxt "constr-name"
+msgid "arc-arc-len-difference"
+msgstr ""
+
+#: constraint.cpp:29
+msgctxt "constr-name"
+msgid "arc-line-len-difference"
+msgstr ""
+
+#: constraint.cpp:30
 msgctxt "constr-name"
 msgid "symmetric"
 msgstr "对称的"
 
-#: constraint.cpp:27
+#: constraint.cpp:31
 msgctxt "constr-name"
 msgid "symmetric-h"
 msgstr "水平对称"
 
-#: constraint.cpp:28
+#: constraint.cpp:32
 msgctxt "constr-name"
 msgid "symmetric-v"
 msgstr "纵向对称"
 
-#: constraint.cpp:29
+#: constraint.cpp:33
 msgctxt "constr-name"
 msgid "symmetric-line"
 msgstr "线对称"
 
-#: constraint.cpp:30
+#: constraint.cpp:34
 msgctxt "constr-name"
 msgid "at-midpoint"
 msgstr "在中点"
 
-#: constraint.cpp:31
+#: constraint.cpp:35
 msgctxt "constr-name"
 msgid "horizontal"
 msgstr "水平约束"
 
-#: constraint.cpp:32
+#: constraint.cpp:36
 msgctxt "constr-name"
 msgid "vertical"
 msgstr "垂直约束"
 
-#: constraint.cpp:33
+#: constraint.cpp:37
 msgctxt "constr-name"
 msgid "diameter"
 msgstr "直径约束"
 
-#: constraint.cpp:34
+#: constraint.cpp:38
 msgctxt "constr-name"
 msgid "pt-on-circle"
 msgstr "圆点约束"
 
-#: constraint.cpp:35
+#: constraint.cpp:39
 msgctxt "constr-name"
 msgid "same-orientation"
 msgstr "相同原点"
 
-#: constraint.cpp:36
+#: constraint.cpp:40
 msgctxt "constr-name"
 msgid "angle"
 msgstr "角度约束"
 
-#: constraint.cpp:37
+#: constraint.cpp:41
 msgctxt "constr-name"
 msgid "parallel"
 msgstr "平行约束"
 
-#: constraint.cpp:38
+#: constraint.cpp:42
 msgctxt "constr-name"
 msgid "arc-line-tangent"
 msgstr "弧切线"
 
-#: constraint.cpp:39
+#: constraint.cpp:43
 msgctxt "constr-name"
 msgid "cubic-line-tangent"
 msgstr "立方体切线"
 
-#: constraint.cpp:40
+#: constraint.cpp:44
 msgctxt "constr-name"
 msgid "curve-curve-tangent"
 msgstr "曲线间切线"
 
-#: constraint.cpp:41
+#: constraint.cpp:45
 msgctxt "constr-name"
 msgid "perpendicular"
 msgstr "垂直约束"
 
-#: constraint.cpp:42
+#: constraint.cpp:46
 msgctxt "constr-name"
 msgid "eq-radius"
 msgstr "等于半径"
 
-#: constraint.cpp:43
+#: constraint.cpp:47
 msgctxt "constr-name"
 msgid "eq-angle"
 msgstr "等于角度"
 
-#: constraint.cpp:44
+#: constraint.cpp:48
 msgctxt "constr-name"
 msgid "eq-line-len-arc-len"
 msgstr "等于线长或弧长"
 
-#: constraint.cpp:45
+#: constraint.cpp:49
 msgctxt "constr-name"
 msgid "lock-where-dragged"
 msgstr "锁定位置"
 
-#: constraint.cpp:46
+#: constraint.cpp:50
 msgctxt "constr-name"
 msgid "comment"
 msgstr "备注"
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with "
 "Constrain -> On Point before constraining tangent."
 msgstr "切线弧和线段必须共享一个端点。在约束切线之前,使用约束 -= 点约束它们。"
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them "
 "with Constrain -> On Point before constraining tangent."
 msgstr ""
 "切线立方段和线段必须共享终结点。在约束切线之前,使用约束 -= 点约束它们。"
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point "
 "before constraining tangent."
 msgstr "曲线必须共享一个终结点。在约束切线之前,使用约束 -= 点约束它们。"
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply "
 "to:\n"
@@ -313,7 +333,7 @@ msgstr ""
 "    * 平面面和点(最小距离)\n"
 "    * 圆或弧(直径)\n"
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can "
 "apply to:\n"
@@ -332,7 +352,7 @@ msgstr ""
 "    * 一个点和一个圆或圆(曲线上的点)\n"
 "    * 点和平面面(点在脸上)\n"
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can "
 "apply to:\n"
@@ -358,28 +378,26 @@ msgstr ""
 "    * 两个圆或圆(相等半径)\n"
 "    * 线段和圆弧(线段长度等于弧长)\n"
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"长度比率约束的选择错误。此约束可应用于:\n"
-"\n"
-"* 两个线段\n"
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply "
 "to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
-"长度差异约束的选择错误。此约束可应用于:\n"
-"\n"
-"* 两个线段\n"
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -391,7 +409,7 @@ msgstr ""
 "* 线段和点(点在中点)\n"
 "    * 线段和工作平面(平面上的线中点)\n"
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -408,19 +426,19 @@ msgstr ""
 "    * 线段,和两个点或线段(对称的线段)\n"
 "    * 工作平面和两个点或线段(工作平面对称)\n"
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid ""
 "A workplane must be active when constraining symmetric without an explicit "
 "symmetry plane."
 msgstr "在没有显式对称平面约束对称时,工作平面必须处于活动状态。"
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a "
 "horizontal or vertical constraint."
 msgstr "在应用水平或垂直约束之前,激活工作平面(使用草图 -= 在工作平面中)。"
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can "
 "apply to:\n"
@@ -433,7 +451,7 @@ msgstr ""
 "• 两点\n"
 "    • 线段\n"
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply "
 "to:\n"
@@ -444,15 +462,15 @@ msgstr ""
 "\n"
 "• 两个法线\n"
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr "必须选择角度约束。"
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr "必须选择具有关联标签的约束。"
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -466,11 +484,11 @@ msgstr ""
 "    * 线段和法线\n"
 "    • 两个法线\n"
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr "曲线曲线切线必须应用于工作平面。"
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply "
 "to:\n"
@@ -487,7 +505,7 @@ msgstr ""
 "    * 两个法线(平行)\n"
 "    * 共享端点的两条线段、弧线或贝塞尔(切线)\n"
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -501,7 +519,7 @@ msgstr ""
 "    * 线段和法线\n"
 "    • 两个法线\n"
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can "
 "apply to:\n"
@@ -512,7 +530,11 @@ msgstr ""
 "\n"
 "• 一点\n"
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr "新备注 - 双击编辑"
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr "单击注释文本的中心"
 
@@ -538,24 +560,24 @@ msgstr ""
 "    * 脸(通过面的剖面)\n"
 "    * 一个点和两个线段(平面穿过点和平行线)\n"
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
 msgstr "活动组网格为空;没有要导出的。"
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr "徒手线替换为连续线"
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr "锯齿线替换为连续线"
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid ""
 "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr "绘图的某些方面没有 DXF 等效项,并且未导出:\n"
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid ""
 "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr "PDF 页面大小超过 200 英寸或 200 英寸;许多查看器可能会拒绝此文件。"
@@ -570,24 +592,28 @@ msgctxt "group-name"
 msgid "#references"
 msgstr "#参考"
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr ""
+
+#: file.cpp:555
 msgid ""
 "Unrecognized data in file. This file may be corrupt, or from a newer version "
 "of the program."
 msgstr "未识别文件内数据。该文件可能损坏,或使用新版本应用程序尝试打开。"
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr "文件丢失"
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
 msgstr "连接的文件不存在:\"%s\"。"
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -596,17 +622,17 @@ msgid ""
 "permanently removed."
 msgstr "您是否想手工查找?如果是,所有基于该丢失文件的几何对象将会被全部删除."
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr "是(&Y)"
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr "否(&N)"
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr "取消(&C)"
@@ -780,295 +806,307 @@ msgid "Use &Perspective Projection"
 msgstr "使用远景透视(&P)"
 
 #: graphicswin.cpp:97
+msgid "Show E&xploded View"
+msgstr ""
+
+#: graphicswin.cpp:98
 msgid "Dimension &Units"
 msgstr "标注单位(&U)"
 
-#: graphicswin.cpp:98
+#: graphicswin.cpp:99
 msgid "Dimensions in &Millimeters"
 msgstr "标注单位 mm (&M)"
 
-#: graphicswin.cpp:99
+#: graphicswin.cpp:100
 msgid "Dimensions in M&eters"
 msgstr "标注单位m (&E)"
 
-#: graphicswin.cpp:100
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr "标准单位英寸 (&I)"
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr ""
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr "显示工具条(&T)"
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr "显示属性浏览器(&W)"
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr "全屏(&F)"
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr "新组合(&N)"
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr "在三维内绘制(&3)"
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr "在新工作面绘制(&W)"
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr "移动(&T)"
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr "旋转(&R)"
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr "挤出(&E)"
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
 msgstr "螺旋(&H)"
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr "扫略(&L)"
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
 msgstr "旋转(&V)"
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
 msgstr "链接/装配..."
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr "连接最近文件"
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr "绘图(&S)"
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr "在工作平面(&W)"
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr "在3D的任何位置(&3)"
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr "基准点(&P)"
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr "工作面(&W)"
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr "线段(&S)"
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr "构造线段(&C)"
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr "矩形(&R)"
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr "圆线(&C)"
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr "圆弧(&A)"
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr "立方体线的贝塞尔曲线(&B)"
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr "TrueTyoe字体文字(&T)"
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr "图片(&I)"
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr "切换构造(&G)"
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr "弧线切线点(&A)"
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr "在交叉处拆分曲线(&I)"
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr "约束(&C)"
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr "距离/直径(&D)"
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr "参考标注(&F)"
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr "角度(&A)"
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr "参考角度(&G)"
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr "其它增补角度(&U)"
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr "切换参考标注(&E)"
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr "水平约束(&H)"
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr "垂直约束(&V)"
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr "在点线面(&O)"
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr "等于/长度/半径/角度(&Q)"
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
-msgstr "长度比例(&T)"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
+msgstr ""
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
-msgstr "长度偏差(&E)"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
+msgstr ""
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr "在中点(&M)"
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr "对称(&Y)"
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr "水平/切线(&L)"
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr "垂直的(&P)"
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr "相同方向(&A)"
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr "锁定点位置(&D)"
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr "备注"
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr "分析(&A)"
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr "测量体积(&V)"
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr "测量面积(&R)"
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr "测量周长(&P)"
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr "显示干涉零件(&I)"
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr "显示孤立边(&N)"
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
 msgstr "显示中心(&C)"
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
 msgstr "显示无效约束点(&U)"
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr "跟踪点(&T)"
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr "停止跟踪(&S)"
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr "逐步标注(&D)"
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr "帮助(&H)"
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr "语言(&L)"
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr "网页/手册(&W)"
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr "关于(&A)"
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr "(无文件)"
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
 msgstr "文件不存在: \"%s\"。"
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr "没有激活的工作面,因此无法显示轴网。"
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel "
 "projection.\n"
@@ -1077,91 +1115,91 @@ msgid ""
 "configuration screen. A value around 0.3 is typical."
 msgstr ""
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid ""
 "Select a point; this point will become the center of the view on screen."
 msgstr ""
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr ""
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or "
 "make a link group the active group."
 msgstr ""
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) "
 "to define the plane for the snap grid."
 msgstr ""
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints "
 "with a label. To snap a line, select its endpoints."
 msgstr ""
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default "
 "workplane. Try selecting a workplane, or activating a sketch-in-new-"
 "workplane group."
 msgstr ""
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select "
 "nothing to set up arc parameters."
 msgstr ""
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr "点击弧线的点(逆时针方向绘制)"
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr "点击放置基准点"
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr "点击线条的起点"
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr "点击构造线的起点"
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr "点击立方体的起点"
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr "点击圆弧的中心"
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr "点击工作面的原点"
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr "点击一个矩形倒角"
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr "点击文字左上角"
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr "点击图片左上角"
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid ""
 "No entities are selected. Select entities before trying to toggle their "
 "construction state."
@@ -1172,37 +1210,33 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr "3D草图"
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the "
 "lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
-"在新工作面内绘图选择失败,该组可以使用:\n"
-"\n"
-"    * 一个点(通过该点,正交至坐标轴)\n"
-"   * 一个点和二个线段(通过点,绘制平行线至线段)\n"
-"   * 一个工作面(复制工作面)\n"
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch "
 "will be extruded normal to the workplane."
 msgstr "挤出前先激活工作面(草图->在工作面),该草图将由工作面的法线方向挤出。"
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr "挤出"
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr "扫略操作仅可用于二维草图。"
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1215,16 +1249,16 @@ msgstr ""
 "   * 一个点和一个线段或法线(围绕坐标轴至线或法线的平行线,通过点)\n"
 "   * 一个线段(围绕线段)\n"
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr "扫略"
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1233,16 +1267,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
 msgstr "旋转"
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1251,12 +1285,12 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
 msgstr "螺旋"
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1266,428 +1300,438 @@ msgid ""
 "point, and parallel to line / normal)\n"
 msgstr ""
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr "旋转"
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr "移动"
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr "(未命名)"
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
-msgstr "未闭合轮廓或样式不一致!"
+msgstr "未闭合轮廓 , 或样式不一致!"
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr "点不在相同平面!"
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr "轮廓自相交!"
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr "边缘长度为零!"
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr ""
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr ""
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or "
 "circles in this group and workplane join."
 msgstr ""
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the "
 "desired geometry by hand with tangency constraints."
 msgstr ""
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr ""
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs "
 "or a line/circle/arc and a point)."
 msgstr ""
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr "无法拆分;未发现较差点。"
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr "指定样式"
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr "无样式"
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr "新组样式。"
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr "组信息"
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr "样式信息"
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr "选择边缘链"
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr "切换参考标注"
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr "其它补充角度"
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr "捕捉至轴网"
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr "删除样条线的点"
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr "增加样条线的点"
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr "无法增加样条线点:超过最大限制。"
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr "切换构造"
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr "删除点一致约束"
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr "剪切"
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr "复制"
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr "全选"
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr "粘贴"
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr "粘贴移动的..."
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr "删除"
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr "取消全选"
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr "取消覆盖区域的全选"
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr "自动缩放"
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr "点击下一个点或取消(ESC)"
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid ""
 "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "无法在3D内绘制矩形; 首先,激活工作面,草图->在工作面。"
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr "点击放置其它矩形倒角"
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr "点击设置半径"
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid ""
 "Can't draw arc in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "无法在3D空间内绘制弧线,可使用 草图->在工作面 激活工作面。"
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr "点击放置点"
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr "点击下一个点或取消(ESC)"
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid ""
 "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr "已经在工作面绘制;在新建工作面前在三维空间绘制。"
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid ""
 "Can't draw text in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "无法在三维空间内绘制文字,可使用 草图->在工作面 激活工作面。"
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
 msgstr "点击文字的右下角放置"
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid ""
 "Can't draw image in 3d; first, activate a workplane with Sketch -> In "
 "Workplane."
 msgstr "无法在三维空间内绘制图片,可使用 草图->在工作面 激活工作面。"
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
-msgstr "新备注 - 双击编辑"
-
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
 msgctxt "file-type"
 msgid "SolveSpace models"
 msgstr "SolveSpace模型"
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:89
+msgctxt "file-type"
+msgid "ALL"
+msgstr ""
+
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
 msgstr ""
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr ""
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr "PNG图片"
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr "STL网格"
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr "Wavefront OBJ网格"
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
 msgstr "Three.js-网格及查看视图"
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr "Three.js-仅网格"
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
 msgstr "VRML文本文件"
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr "STEP文件"
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr "PDF文件"
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr "封装好的PostScript"
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr "SVG矢量图"
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr "DXF文件(AutoCAD 2007)"
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr "HPGL文件"
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr "G Code"
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr "AutoCAD DXF/DWG文件"
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr "逗号分隔数据"
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr "未命名"
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr "保存文件"
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr "打开文件"
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr "取消_C"
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr "保存_S"
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
 msgstr "打开_O"
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr ""
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
 msgstr ""
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
 msgstr ""
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
 msgstr ""
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
 msgstr ""
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr ""
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
 msgstr ""
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
 msgstr ""
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
 msgstr ""
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
 msgstr ""
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
 msgstr ""
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr ""
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr ""
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This "
 "is probably not what you want; hide them by clicking the link at the top of "
 "the text window."
 msgstr ""
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid ""
 "Can't identify file type from file extension of filename '%s'; try .dxf or ."
 "dwg."
 msgstr ""
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
 msgstr ""
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr ""
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr ""
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
@@ -1695,7 +1739,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1704,7 +1748,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1712,7 +1756,7 @@ msgid ""
 "This introduces error, typically of around 1%."
 msgstr ""
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1723,13 +1767,13 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, "
 "not coplanar, or self-intersecting."
 msgstr ""
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1740,7 +1784,7 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1751,36 +1795,36 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr ""
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
 msgstr ""
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
 msgstr ""
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1788,7 +1832,7 @@ msgid ""
 "The model contains %d triangles, from %d surfaces."
 msgstr ""
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1798,7 +1842,7 @@ msgid ""
 "Zero problematic edges, good.%s"
 msgstr ""
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1808,7 +1852,7 @@ msgid ""
 "%d problematic edges, bad.%s"
 msgstr ""
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1825,33 +1869,33 @@ msgid ""
 "© 2008-%d Jonathan Westhues and other authors.\n"
 msgstr ""
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try "
 "assigning a style to this entity's parent."
 msgstr "无法将样式分配给派生自其他实体的实体;尝试将样式分配给此实体的父级。"
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
 msgstr "样式名称不能为空"
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr "不能重复少于 1 次。"
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr "重复不超过 999 次。"
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
 msgstr "组名称不能为空"
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr "不透明度必须在零和 1 之间。"
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr "半径偏移不能为负数。"
 
@@ -2006,14 +2050,54 @@ msgctxt "button"
 msgid "&OK"
 msgstr "&OK"
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr "缩放不能为零。"
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr "格式错误: 需指定 x, y, z"
 
+#~ msgid ""
+#~ "Bad selection for length ratio constraint. This constraint can apply to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "长度比率约束的选择错误。此约束可应用于:\n"
+#~ "\n"
+#~ "* 两个线段\n"
+
+#~ msgid ""
+#~ "Bad selection for length difference constraint. This constraint can apply "
+#~ "to:\n"
+#~ "\n"
+#~ "    * two line segments\n"
+#~ msgstr ""
+#~ "长度差异约束的选择错误。此约束可应用于:\n"
+#~ "\n"
+#~ "* 两个线段\n"
+
+#~ msgid "Length Ra&tio"
+#~ msgstr "长度比例(&T)"
+
+#~ msgid "Length Diff&erence"
+#~ msgstr "长度偏差(&E)"
+
+#~ msgid ""
+#~ "Bad selection for new sketch in workplane. This group can be created "
+#~ "with:\n"
+#~ "\n"
+#~ "    * a point (through the point, orthogonal to coordinate axes)\n"
+#~ "    * a point and two line segments (through the point, parallel to the "
+#~ "lines)\n"
+#~ "    * a workplane (copy of the workplane)\n"
+#~ msgstr ""
+#~ "在新工作面内绘图选择失败,该组可以使用:\n"
+#~ "\n"
+#~ "    * 一个点(通过该点,正交至坐标轴)\n"
+#~ "   * 一个点和二个线段(通过点,绘制平行线至线段)\n"
+#~ "   * 一个工作面(复制工作面)\n"
+
 #~ msgctxt "file-type"
 #~ msgid "Q3D Object file"
 #~ msgstr "Q3D对象文件"
index c5ce2b775ddb521ed41338806a0cc7683203b1fb..bf8c9803ed15e42c8321a0ad84f4ee7350543cda 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: SolveSpace 3.0\n"
 "Report-Msgid-Bugs-To: whitequark@whitequark.org\n"
-"POT-Creation-Date: 2021-01-17 19:54+0200\n"
+"POT-Creation-Date: 2022-02-01 16:24+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,76 +17,76 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: clipboard.cpp:310
+#: clipboard.cpp:309
 msgid ""
 "Cut, paste, and copy work only in a workplane.\n"
 "\n"
 "Activate one with Sketch -> In Workplane."
 msgstr ""
 
-#: clipboard.cpp:327
+#: clipboard.cpp:326
 msgid "Clipboard is empty; nothing to paste."
 msgstr ""
 
-#: clipboard.cpp:374
+#: clipboard.cpp:373
 msgid "Number of copies to paste must be at least one."
 msgstr ""
 
-#: clipboard.cpp:390 textscreens.cpp:783
+#: clipboard.cpp:389 textscreens.cpp:833
 msgid "Scale cannot be zero."
 msgstr ""
 
-#: clipboard.cpp:432
+#: clipboard.cpp:431
 msgid "Select one point to define origin of rotation."
 msgstr ""
 
-#: clipboard.cpp:444
+#: clipboard.cpp:443
 msgid "Select two points to define translation vector."
 msgstr ""
 
-#: clipboard.cpp:454
+#: clipboard.cpp:453
 msgid "Transformation is identity. So all copies will be exactly on top of each other."
 msgstr ""
 
-#: clipboard.cpp:458
+#: clipboard.cpp:457
 msgid "Too many items to paste; split this into smaller pastes."
 msgstr ""
 
-#: clipboard.cpp:463
+#: clipboard.cpp:462
 msgid "No workplane active."
 msgstr ""
 
-#: confscreen.cpp:418
+#: confscreen.cpp:381
 msgid "Bad format: specify coordinates as x, y, z"
 msgstr ""
 
-#: confscreen.cpp:428 style.cpp:659 textscreens.cpp:805
+#: confscreen.cpp:391 style.cpp:729 textscreens.cpp:864
 msgid "Bad format: specify color as r, g, b"
 msgstr ""
 
-#: confscreen.cpp:454
+#: confscreen.cpp:417
 msgid ""
 "The perspective factor will have no effect until you enable View -> Use Perspective Projection."
 msgstr ""
 
-#: confscreen.cpp:467 confscreen.cpp:477
+#: confscreen.cpp:435 confscreen.cpp:445
 #, c-format
 msgid "Specify between 0 and %d digits after the decimal."
 msgstr ""
 
-#: confscreen.cpp:489
+#: confscreen.cpp:457
 msgid "Export scale must not be zero!"
 msgstr ""
 
-#: confscreen.cpp:501
+#: confscreen.cpp:469
 msgid "Cutter radius offset must not be negative!"
 msgstr ""
 
-#: confscreen.cpp:555
+#: confscreen.cpp:528
 msgid "Bad value: autosave interval should be positive"
 msgstr ""
 
-#: confscreen.cpp:558
+#: confscreen.cpp:531
 msgid "Bad format: specify interval in integral minutes"
 msgstr ""
 
@@ -157,133 +157,153 @@ msgstr ""
 
 #: constraint.cpp:25
 msgctxt "constr-name"
-msgid "length-difference"
+msgid "arc-arc-length-ratio"
 msgstr ""
 
 #: constraint.cpp:26
 msgctxt "constr-name"
-msgid "symmetric"
+msgid "arc-line-length-ratio"
 msgstr ""
 
 #: constraint.cpp:27
 msgctxt "constr-name"
-msgid "symmetric-h"
+msgid "length-difference"
 msgstr ""
 
 #: constraint.cpp:28
 msgctxt "constr-name"
-msgid "symmetric-v"
+msgid "arc-arc-len-difference"
 msgstr ""
 
 #: constraint.cpp:29
 msgctxt "constr-name"
-msgid "symmetric-line"
+msgid "arc-line-len-difference"
 msgstr ""
 
 #: constraint.cpp:30
 msgctxt "constr-name"
-msgid "at-midpoint"
+msgid "symmetric"
 msgstr ""
 
 #: constraint.cpp:31
 msgctxt "constr-name"
-msgid "horizontal"
+msgid "symmetric-h"
 msgstr ""
 
 #: constraint.cpp:32
 msgctxt "constr-name"
-msgid "vertical"
+msgid "symmetric-v"
 msgstr ""
 
 #: constraint.cpp:33
 msgctxt "constr-name"
-msgid "diameter"
+msgid "symmetric-line"
 msgstr ""
 
 #: constraint.cpp:34
 msgctxt "constr-name"
-msgid "pt-on-circle"
+msgid "at-midpoint"
 msgstr ""
 
 #: constraint.cpp:35
 msgctxt "constr-name"
-msgid "same-orientation"
+msgid "horizontal"
 msgstr ""
 
 #: constraint.cpp:36
 msgctxt "constr-name"
-msgid "angle"
+msgid "vertical"
 msgstr ""
 
 #: constraint.cpp:37
 msgctxt "constr-name"
-msgid "parallel"
+msgid "diameter"
 msgstr ""
 
 #: constraint.cpp:38
 msgctxt "constr-name"
-msgid "arc-line-tangent"
+msgid "pt-on-circle"
 msgstr ""
 
 #: constraint.cpp:39
 msgctxt "constr-name"
-msgid "cubic-line-tangent"
+msgid "same-orientation"
 msgstr ""
 
 #: constraint.cpp:40
 msgctxt "constr-name"
-msgid "curve-curve-tangent"
+msgid "angle"
 msgstr ""
 
 #: constraint.cpp:41
 msgctxt "constr-name"
-msgid "perpendicular"
+msgid "parallel"
 msgstr ""
 
 #: constraint.cpp:42
 msgctxt "constr-name"
-msgid "eq-radius"
+msgid "arc-line-tangent"
 msgstr ""
 
 #: constraint.cpp:43
 msgctxt "constr-name"
-msgid "eq-angle"
+msgid "cubic-line-tangent"
 msgstr ""
 
 #: constraint.cpp:44
 msgctxt "constr-name"
-msgid "eq-line-len-arc-len"
+msgid "curve-curve-tangent"
 msgstr ""
 
 #: constraint.cpp:45
 msgctxt "constr-name"
-msgid "lock-where-dragged"
+msgid "perpendicular"
 msgstr ""
 
 #: constraint.cpp:46
 msgctxt "constr-name"
+msgid "eq-radius"
+msgstr ""
+
+#: constraint.cpp:47
+msgctxt "constr-name"
+msgid "eq-angle"
+msgstr ""
+
+#: constraint.cpp:48
+msgctxt "constr-name"
+msgid "eq-line-len-arc-len"
+msgstr ""
+
+#: constraint.cpp:49
+msgctxt "constr-name"
+msgid "lock-where-dragged"
+msgstr ""
+
+#: constraint.cpp:50
+msgctxt "constr-name"
 msgid "comment"
 msgstr ""
 
-#: constraint.cpp:140
+#: constraint.cpp:144
 msgid ""
 "The tangent arc and line segment must share an endpoint. Constrain them with Constrain -> On "
 "Point before constraining tangent."
 msgstr ""
 
-#: constraint.cpp:158
+#: constraint.cpp:163
 msgid ""
 "The tangent cubic and line segment must share an endpoint. Constrain them with Constrain -> On "
 "Point before constraining tangent."
 msgstr ""
 
-#: constraint.cpp:183
+#: constraint.cpp:189
 msgid ""
 "The curves must share an endpoint. Constrain them with Constrain -> On Point before constraining "
 "tangent."
 msgstr ""
 
-#: constraint.cpp:231
+#: constraint.cpp:238
 msgid ""
 "Bad selection for distance / diameter constraint. This constraint can apply to:\n"
 "\n"
@@ -296,7 +316,7 @@ msgid ""
 "    * a circle or an arc (diameter)\n"
 msgstr ""
 
-#: constraint.cpp:284
+#: constraint.cpp:291
 msgid ""
 "Bad selection for on point / curve / plane constraint. This constraint can apply to:\n"
 "\n"
@@ -307,7 +327,7 @@ msgid ""
 "    * a point and a plane face (point on face)\n"
 msgstr ""
 
-#: constraint.cpp:346
+#: constraint.cpp:353
 msgid ""
 "Bad selection for equal length / radius constraint. This constraint can apply to:\n"
 "\n"
@@ -321,21 +341,25 @@ msgid ""
 "    * a line segment and an arc (line segment length equals arc length)\n"
 msgstr ""
 
-#: constraint.cpp:385
+#: constraint.cpp:407
 msgid ""
 "Bad selection for length ratio constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 
-#: constraint.cpp:402
+#: constraint.cpp:441
 msgid ""
 "Bad selection for length difference constraint. This constraint can apply to:\n"
 "\n"
 "    * two line segments\n"
+"    * two arcs\n"
+"    * one arc and one line segment\n"
 msgstr ""
 
-#: constraint.cpp:428
+#: constraint.cpp:472
 msgid ""
 "Bad selection for at midpoint constraint. This constraint can apply to:\n"
 "\n"
@@ -343,7 +367,7 @@ msgid ""
 "    * a line segment and a workplane (line's midpoint on plane)\n"
 msgstr ""
 
-#: constraint.cpp:486
+#: constraint.cpp:530
 msgid ""
 "Bad selection for symmetric constraint. This constraint can apply to:\n"
 "\n"
@@ -352,17 +376,17 @@ msgid ""
 "    * workplane, and two points or a line segment (symmetric about workplane)\n"
 msgstr ""
 
-#: constraint.cpp:500
+#: constraint.cpp:545
 msgid "A workplane must be active when constraining symmetric without an explicit symmetry plane."
 msgstr ""
 
-#: constraint.cpp:530
+#: constraint.cpp:579
 msgid ""
 "Activate a workplane (with Sketch -> In Workplane) before applying a horizontal or vertical "
 "constraint."
 msgstr ""
 
-#: constraint.cpp:543
+#: constraint.cpp:592
 msgid ""
 "Bad selection for horizontal / vertical constraint. This constraint can apply to:\n"
 "\n"
@@ -370,22 +394,22 @@ msgid ""
 "    * a line segment\n"
 msgstr ""
 
-#: constraint.cpp:564
+#: constraint.cpp:613
 msgid ""
 "Bad selection for same orientation constraint. This constraint can apply to:\n"
 "\n"
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:614
+#: constraint.cpp:663
 msgid "Must select an angle constraint."
 msgstr ""
 
-#: constraint.cpp:627
+#: constraint.cpp:676
 msgid "Must select a constraint with associated label."
 msgstr ""
 
-#: constraint.cpp:638
+#: constraint.cpp:687
 msgid ""
 "Bad selection for angle constraint. This constraint can apply to:\n"
 "\n"
@@ -394,11 +418,11 @@ msgid ""
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:701
+#: constraint.cpp:754
 msgid "Curve-curve tangency must apply in workplane."
 msgstr ""
 
-#: constraint.cpp:711
+#: constraint.cpp:766
 msgid ""
 "Bad selection for parallel / tangent constraint. This constraint can apply to:\n"
 "\n"
@@ -408,7 +432,7 @@ msgid ""
 "    * two line segments, arcs, or beziers, that share an endpoint (tangent)\n"
 msgstr ""
 
-#: constraint.cpp:729
+#: constraint.cpp:784
 msgid ""
 "Bad selection for perpendicular constraint. This constraint can apply to:\n"
 "\n"
@@ -417,14 +441,18 @@ msgid ""
 "    * two normals\n"
 msgstr ""
 
-#: constraint.cpp:744
+#: constraint.cpp:799
 msgid ""
 "Bad selection for lock point where dragged constraint. This constraint can apply to:\n"
 "\n"
 "    * a point\n"
 msgstr ""
 
-#: constraint.cpp:755
+#: constraint.cpp:813 mouse.cpp:1158
+msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+msgstr ""
+
+#: constraint.cpp:818
 msgid "click center of comment text"
 msgstr ""
 
@@ -443,23 +471,23 @@ msgid ""
 "    * a point and two line segments (plane through point and parallel to lines)\n"
 msgstr ""
 
-#: export.cpp:822
+#: export.cpp:818
 msgid "Active group mesh is empty; nothing to export."
 msgstr ""
 
-#: exportvector.cpp:337
+#: exportvector.cpp:336
 msgid "freehand lines were replaced with continuous lines"
 msgstr ""
 
-#: exportvector.cpp:339
+#: exportvector.cpp:338
 msgid "zigzag lines were replaced with continuous lines"
 msgstr ""
 
-#: exportvector.cpp:593
+#: exportvector.cpp:592
 msgid "Some aspects of the drawing have no DXF equivalent and were not exported:\n"
 msgstr ""
 
-#: exportvector.cpp:839
+#: exportvector.cpp:838
 msgid "PDF page size exceeds 200 by 200 inches; many viewers may reject this file."
 msgstr ""
 
@@ -473,22 +501,26 @@ msgctxt "group-name"
 msgid "#references"
 msgstr ""
 
-#: file.cpp:549
+#: file.cpp:550
+msgid "The file is empty. It may be corrupt."
+msgstr ""
+
+#: file.cpp:555
 msgid "Unrecognized data in file. This file may be corrupt, or from a newer version of the program."
 msgstr ""
 
-#: file.cpp:859
+#: file.cpp:867
 msgctxt "title"
 msgid "Missing File"
 msgstr ""
 
-#: file.cpp:860
+#: file.cpp:868
 #, c-format
 msgctxt "dialog"
 msgid "The linked file “%s” is not present."
 msgstr ""
 
-#: file.cpp:862
+#: file.cpp:870
 msgctxt "dialog"
 msgid ""
 "Do you want to locate it manually?\n"
@@ -496,17 +528,17 @@ msgid ""
 "If you decline, any geometry that depends on the missing file will be permanently removed."
 msgstr ""
 
-#: file.cpp:865
+#: file.cpp:873
 msgctxt "button"
 msgid "&Yes"
 msgstr ""
 
-#: file.cpp:867
+#: file.cpp:875
 msgctxt "button"
 msgid "&No"
 msgstr ""
 
-#: file.cpp:869 solvespace.cpp:569
+#: file.cpp:877 solvespace.cpp:611
 msgctxt "button"
 msgid "&Cancel"
 msgstr ""
@@ -680,295 +712,307 @@ msgid "Use &Perspective Projection"
 msgstr ""
 
 #: graphicswin.cpp:97
-msgid "Dimension &Units"
+msgid "Show E&xploded View"
 msgstr ""
 
 #: graphicswin.cpp:98
-msgid "Dimensions in &Millimeters"
+msgid "Dimension &Units"
 msgstr ""
 
 #: graphicswin.cpp:99
-msgid "Dimensions in M&eters"
+msgid "Dimensions in &Millimeters"
 msgstr ""
 
 #: graphicswin.cpp:100
+msgid "Dimensions in M&eters"
+msgstr ""
+
+#: graphicswin.cpp:101
 msgid "Dimensions in &Inches"
 msgstr ""
 
 #: graphicswin.cpp:102
+msgid "Dimensions in &Feet and Inches"
+msgstr ""
+
+#: graphicswin.cpp:104
 msgid "Show &Toolbar"
 msgstr ""
 
-#: graphicswin.cpp:103
+#: graphicswin.cpp:105
 msgid "Show Property Bro&wser"
 msgstr ""
 
-#: graphicswin.cpp:105
+#: graphicswin.cpp:107
 msgid "&Full Screen"
 msgstr ""
 
-#: graphicswin.cpp:107
+#: graphicswin.cpp:109
 msgid "&New Group"
 msgstr ""
 
-#: graphicswin.cpp:108
+#: graphicswin.cpp:110
 msgid "Sketch In &3d"
 msgstr ""
 
-#: graphicswin.cpp:109
+#: graphicswin.cpp:111
 msgid "Sketch In New &Workplane"
 msgstr ""
 
-#: graphicswin.cpp:111
+#: graphicswin.cpp:113
 msgid "Step &Translating"
 msgstr ""
 
-#: graphicswin.cpp:112
+#: graphicswin.cpp:114
 msgid "Step &Rotating"
 msgstr ""
 
-#: graphicswin.cpp:114
+#: graphicswin.cpp:116
 msgid "E&xtrude"
 msgstr ""
 
-#: graphicswin.cpp:115
+#: graphicswin.cpp:117
 msgid "&Helix"
 msgstr ""
 
-#: graphicswin.cpp:116
+#: graphicswin.cpp:118
 msgid "&Lathe"
 msgstr ""
 
-#: graphicswin.cpp:117
+#: graphicswin.cpp:119
 msgid "Re&volve"
 msgstr ""
 
-#: graphicswin.cpp:119
+#: graphicswin.cpp:121
 msgid "Link / Assemble..."
 msgstr ""
 
-#: graphicswin.cpp:120
+#: graphicswin.cpp:122
 msgid "Link Recent"
 msgstr ""
 
-#: graphicswin.cpp:122
+#: graphicswin.cpp:124
 msgid "&Sketch"
 msgstr ""
 
-#: graphicswin.cpp:123
+#: graphicswin.cpp:125
 msgid "In &Workplane"
 msgstr ""
 
-#: graphicswin.cpp:124
+#: graphicswin.cpp:126
 msgid "Anywhere In &3d"
 msgstr ""
 
-#: graphicswin.cpp:126
+#: graphicswin.cpp:128
 msgid "Datum &Point"
 msgstr ""
 
-#: graphicswin.cpp:127
+#: graphicswin.cpp:129
 msgid "&Workplane"
 msgstr ""
 
-#: graphicswin.cpp:129
+#: graphicswin.cpp:131
 msgid "Line &Segment"
 msgstr ""
 
-#: graphicswin.cpp:130
+#: graphicswin.cpp:132
 msgid "C&onstruction Line Segment"
 msgstr ""
 
-#: graphicswin.cpp:131
+#: graphicswin.cpp:133
 msgid "&Rectangle"
 msgstr ""
 
-#: graphicswin.cpp:132
+#: graphicswin.cpp:134
 msgid "&Circle"
 msgstr ""
 
-#: graphicswin.cpp:133
+#: graphicswin.cpp:135
 msgid "&Arc of a Circle"
 msgstr ""
 
-#: graphicswin.cpp:134
+#: graphicswin.cpp:136
 msgid "&Bezier Cubic Spline"
 msgstr ""
 
-#: graphicswin.cpp:136
+#: graphicswin.cpp:138
 msgid "&Text in TrueType Font"
 msgstr ""
 
-#: graphicswin.cpp:137
+#: graphicswin.cpp:139
 msgid "&Image"
 msgstr ""
 
-#: graphicswin.cpp:139
+#: graphicswin.cpp:141
 msgid "To&ggle Construction"
 msgstr ""
 
-#: graphicswin.cpp:140
+#: graphicswin.cpp:142
 msgid "Tangent &Arc at Point"
 msgstr ""
 
-#: graphicswin.cpp:141
+#: graphicswin.cpp:143
 msgid "Split Curves at &Intersection"
 msgstr ""
 
-#: graphicswin.cpp:143
+#: graphicswin.cpp:145
 msgid "&Constrain"
 msgstr ""
 
-#: graphicswin.cpp:144
+#: graphicswin.cpp:146
 msgid "&Distance / Diameter"
 msgstr ""
 
-#: graphicswin.cpp:145
+#: graphicswin.cpp:147
 msgid "Re&ference Dimension"
 msgstr ""
 
-#: graphicswin.cpp:146
+#: graphicswin.cpp:148
 msgid "A&ngle"
 msgstr ""
 
-#: graphicswin.cpp:147
+#: graphicswin.cpp:149
 msgid "Reference An&gle"
 msgstr ""
 
-#: graphicswin.cpp:148
+#: graphicswin.cpp:150
 msgid "Other S&upplementary Angle"
 msgstr ""
 
-#: graphicswin.cpp:149
+#: graphicswin.cpp:151
 msgid "Toggle R&eference Dim"
 msgstr ""
 
-#: graphicswin.cpp:151
+#: graphicswin.cpp:153
 msgid "&Horizontal"
 msgstr ""
 
-#: graphicswin.cpp:152
+#: graphicswin.cpp:154
 msgid "&Vertical"
 msgstr ""
 
-#: graphicswin.cpp:154
+#: graphicswin.cpp:156
 msgid "&On Point / Curve / Plane"
 msgstr ""
 
-#: graphicswin.cpp:155
+#: graphicswin.cpp:157
 msgid "E&qual Length / Radius / Angle"
 msgstr ""
 
-#: graphicswin.cpp:156
-msgid "Length Ra&tio"
+#: graphicswin.cpp:158
+msgid "Length / Arc Ra&tio"
 msgstr ""
 
-#: graphicswin.cpp:157
-msgid "Length Diff&erence"
+#: graphicswin.cpp:159
+msgid "Length / Arc Diff&erence"
 msgstr ""
 
-#: graphicswin.cpp:158
+#: graphicswin.cpp:160
 msgid "At &Midpoint"
 msgstr ""
 
-#: graphicswin.cpp:159
+#: graphicswin.cpp:161
 msgid "S&ymmetric"
 msgstr ""
 
-#: graphicswin.cpp:160
+#: graphicswin.cpp:162
 msgid "Para&llel / Tangent"
 msgstr ""
 
-#: graphicswin.cpp:161
+#: graphicswin.cpp:163
 msgid "&Perpendicular"
 msgstr ""
 
-#: graphicswin.cpp:162
+#: graphicswin.cpp:164
 msgid "Same Orient&ation"
 msgstr ""
 
-#: graphicswin.cpp:163
+#: graphicswin.cpp:165
 msgid "Lock Point Where &Dragged"
 msgstr ""
 
-#: graphicswin.cpp:165
+#: graphicswin.cpp:167
 msgid "Comment"
 msgstr ""
 
-#: graphicswin.cpp:167
+#: graphicswin.cpp:169
 msgid "&Analyze"
 msgstr ""
 
-#: graphicswin.cpp:168
+#: graphicswin.cpp:170
 msgid "Measure &Volume"
 msgstr ""
 
-#: graphicswin.cpp:169
+#: graphicswin.cpp:171
 msgid "Measure A&rea"
 msgstr ""
 
-#: graphicswin.cpp:170
+#: graphicswin.cpp:172
 msgid "Measure &Perimeter"
 msgstr ""
 
-#: graphicswin.cpp:171
+#: graphicswin.cpp:173
 msgid "Show &Interfering Parts"
 msgstr ""
 
-#: graphicswin.cpp:172
+#: graphicswin.cpp:174
 msgid "Show &Naked Edges"
 msgstr ""
 
-#: graphicswin.cpp:173
+#: graphicswin.cpp:175
 msgid "Show &Center of Mass"
 msgstr ""
 
-#: graphicswin.cpp:175
+#: graphicswin.cpp:177
 msgid "Show &Underconstrained Points"
 msgstr ""
 
-#: graphicswin.cpp:177
+#: graphicswin.cpp:179
 msgid "&Trace Point"
 msgstr ""
 
-#: graphicswin.cpp:178
+#: graphicswin.cpp:180
 msgid "&Stop Tracing..."
 msgstr ""
 
-#: graphicswin.cpp:179
+#: graphicswin.cpp:181
 msgid "Step &Dimension..."
 msgstr ""
 
-#: graphicswin.cpp:181
+#: graphicswin.cpp:183
 msgid "&Help"
 msgstr ""
 
-#: graphicswin.cpp:182
+#: graphicswin.cpp:184
 msgid "&Language"
 msgstr ""
 
-#: graphicswin.cpp:183
+#: graphicswin.cpp:185
 msgid "&Website / Manual"
 msgstr ""
 
-#: graphicswin.cpp:185
+#: graphicswin.cpp:186
+msgid "&Go to GitHub commit"
+msgstr ""
+
+#: graphicswin.cpp:188
 msgid "&About"
 msgstr ""
 
-#: graphicswin.cpp:355
+#: graphicswin.cpp:362
 msgid "(no recent files)"
 msgstr ""
 
-#: graphicswin.cpp:363
+#: graphicswin.cpp:370
 #, c-format
 msgid "File '%s' does not exist."
 msgstr ""
 
-#: graphicswin.cpp:725
+#: graphicswin.cpp:737
 msgid "No workplane is active, so the grid will not appear."
 msgstr ""
 
-#: graphicswin.cpp:740
+#: graphicswin.cpp:752
 msgid ""
 "The perspective factor is set to zero, so the view will always be a parallel projection.\n"
 "\n"
@@ -976,89 +1020,89 @@ msgid ""
 "around 0.3 is typical."
 msgstr ""
 
-#: graphicswin.cpp:819
+#: graphicswin.cpp:837
 msgid "Select a point; this point will become the center of the view on screen."
 msgstr ""
 
-#: graphicswin.cpp:1114
+#: graphicswin.cpp:1137
 msgid "No additional entities share endpoints with the selected entities."
 msgstr ""
 
-#: graphicswin.cpp:1132
+#: graphicswin.cpp:1155
 msgid ""
 "To use this command, select a point or other entity from an linked part, or make a link group the "
 "active group."
 msgstr ""
 
-#: graphicswin.cpp:1155
+#: graphicswin.cpp:1178
 msgid ""
 "No workplane is active. Activate a workplane (with Sketch -> In Workplane) to define the plane "
 "for the snap grid."
 msgstr ""
 
-#: graphicswin.cpp:1162
+#: graphicswin.cpp:1185
 msgid ""
 "Can't snap these items to grid; select points, text comments, or constraints with a label. To "
 "snap a line, select its endpoints."
 msgstr ""
 
-#: graphicswin.cpp:1247
+#: graphicswin.cpp:1270
 msgid "No workplane selected. Activating default workplane for this group."
 msgstr ""
 
-#: graphicswin.cpp:1250
+#: graphicswin.cpp:1273
 msgid ""
 "No workplane is selected, and the active group does not have a default workplane. Try selecting a "
 "workplane, or activating a sketch-in-new-workplane group."
 msgstr ""
 
-#: graphicswin.cpp:1271
+#: graphicswin.cpp:1294
 msgid ""
 "Bad selection for tangent arc at point. Select a single point, or select nothing to set up arc "
 "parameters."
 msgstr ""
 
-#: graphicswin.cpp:1282
+#: graphicswin.cpp:1305
 msgid "click point on arc (draws anti-clockwise)"
 msgstr ""
 
-#: graphicswin.cpp:1283
+#: graphicswin.cpp:1306
 msgid "click to place datum point"
 msgstr ""
 
-#: graphicswin.cpp:1284
+#: graphicswin.cpp:1307
 msgid "click first point of line segment"
 msgstr ""
 
-#: graphicswin.cpp:1286
+#: graphicswin.cpp:1309
 msgid "click first point of construction line segment"
 msgstr ""
 
-#: graphicswin.cpp:1287
+#: graphicswin.cpp:1310
 msgid "click first point of cubic segment"
 msgstr ""
 
-#: graphicswin.cpp:1288
+#: graphicswin.cpp:1311
 msgid "click center of circle"
 msgstr ""
 
-#: graphicswin.cpp:1289
+#: graphicswin.cpp:1312
 msgid "click origin of workplane"
 msgstr ""
 
-#: graphicswin.cpp:1290
+#: graphicswin.cpp:1313
 msgid "click one corner of rectangle"
 msgstr ""
 
-#: graphicswin.cpp:1291
+#: graphicswin.cpp:1314
 msgid "click top left of text"
 msgstr ""
 
-#: graphicswin.cpp:1297
+#: graphicswin.cpp:1320
 msgid "click top left of image"
 msgstr ""
 
-#: graphicswin.cpp:1309
+#: graphicswin.cpp:1346
 msgid "No entities are selected. Select entities before trying to toggle their construction state."
 msgstr ""
 
@@ -1067,31 +1111,32 @@ msgctxt "group-name"
 msgid "sketch-in-3d"
 msgstr ""
 
-#: group.cpp:142
+#: group.cpp:150
 msgid ""
 "Bad selection for new sketch in workplane. This group can be created with:\n"
 "\n"
 "    * a point (through the point, orthogonal to coordinate axes)\n"
 "    * a point and two line segments (through the point, parallel to the lines)\n"
+"    * a point and a normal (through the point, orthogonal to the normal)\n"
 "    * a workplane (copy of the workplane)\n"
 msgstr ""
 
-#: group.cpp:154
+#: group.cpp:166
 msgid ""
 "Activate a workplane (Sketch -> In Workplane) before extruding. The sketch will be extruded "
 "normal to the workplane."
 msgstr ""
 
-#: group.cpp:163
+#: group.cpp:175
 msgctxt "group-name"
 msgid "extrude"
 msgstr ""
 
-#: group.cpp:168
+#: group.cpp:180
 msgid "Lathe operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:179
+#: group.cpp:191
 msgid ""
 "Bad selection for new lathe group. This group can be created with:\n"
 "\n"
@@ -1100,16 +1145,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:189
+#: group.cpp:201
 msgctxt "group-name"
 msgid "lathe"
 msgstr ""
 
-#: group.cpp:194
+#: group.cpp:206
 msgid "Revolve operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:205
+#: group.cpp:217
 msgid ""
 "Bad selection for new revolve group. This group can be created with:\n"
 "\n"
@@ -1118,16 +1163,16 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:217
+#: group.cpp:229
 msgctxt "group-name"
 msgid "revolve"
 msgstr ""
 
-#: group.cpp:222
+#: group.cpp:234
 msgid "Helix operation can only be applied to planar sketches."
 msgstr ""
 
-#: group.cpp:233
+#: group.cpp:245
 msgid ""
 "Bad selection for new helix group. This group can be created with:\n"
 "\n"
@@ -1136,12 +1181,12 @@ msgid ""
 "    * a line segment (revolved about line segment)\n"
 msgstr ""
 
-#: group.cpp:245
+#: group.cpp:257
 msgctxt "group-name"
 msgid "helix"
 msgstr ""
 
-#: group.cpp:258
+#: group.cpp:270
 msgid ""
 "Bad selection for new rotation. This group can be created with:\n"
 "\n"
@@ -1150,416 +1195,426 @@ msgid ""
 "line / normal)\n"
 msgstr ""
 
-#: group.cpp:271
+#: group.cpp:283
 msgctxt "group-name"
 msgid "rotate"
 msgstr ""
 
-#: group.cpp:282
+#: group.cpp:294
 msgctxt "group-name"
 msgid "translate"
 msgstr ""
 
-#: group.cpp:400
+#: group.cpp:416
 msgid "(unnamed)"
 msgstr ""
 
-#: groupmesh.cpp:709
+#: groupmesh.cpp:707
 msgid "not closed contour, or not all same style!"
 msgstr ""
 
-#: groupmesh.cpp:722
+#: groupmesh.cpp:720
 msgid "points not all coplanar!"
 msgstr ""
 
-#: groupmesh.cpp:724
+#: groupmesh.cpp:722
 msgid "contour is self-intersecting!"
 msgstr ""
 
-#: groupmesh.cpp:726
+#: groupmesh.cpp:724
 msgid "zero-length edge!"
 msgstr ""
 
-#: modify.cpp:254
+#: importmesh.cpp:136
+msgid "Text-formated STL files are not currently supported"
+msgstr ""
+
+#: modify.cpp:252
 msgid "Must be sketching in workplane to create tangent arc."
 msgstr ""
 
-#: modify.cpp:301
+#: modify.cpp:299
 msgid ""
 "To create a tangent arc, select a point where two non-construction lines or circles in this group "
 "and workplane join."
 msgstr ""
 
-#: modify.cpp:388
+#: modify.cpp:386
 msgid ""
 "Couldn't round this corner. Try a smaller radius, or try creating the desired geometry by hand "
 "with tangency constraints."
 msgstr ""
 
-#: modify.cpp:597
+#: modify.cpp:595
 msgid "Couldn't split this entity; lines, circles, or cubics only."
 msgstr ""
 
-#: modify.cpp:624
+#: modify.cpp:622
 msgid "Must be sketching in workplane to split."
 msgstr ""
 
-#: modify.cpp:631
+#: modify.cpp:629
 msgid ""
 "Select two entities that intersect each other (e.g. two lines/circles/arcs or a line/circle/arc "
 "and a point)."
 msgstr ""
 
-#: modify.cpp:736
+#: modify.cpp:734
 msgid "Can't split; no intersection found."
 msgstr ""
 
-#: mouse.cpp:560
+#: mouse.cpp:557
 msgid "Assign to Style"
 msgstr ""
 
-#: mouse.cpp:576
+#: mouse.cpp:573
 msgid "No Style"
 msgstr ""
 
-#: mouse.cpp:579
+#: mouse.cpp:576
 msgid "Newly Created Custom Style..."
 msgstr ""
 
-#: mouse.cpp:586
+#: mouse.cpp:583
 msgid "Group Info"
 msgstr ""
 
-#: mouse.cpp:606
+#: mouse.cpp:603
 msgid "Style Info"
 msgstr ""
 
-#: mouse.cpp:626
+#: mouse.cpp:623
 msgid "Select Edge Chain"
 msgstr ""
 
-#: mouse.cpp:632
+#: mouse.cpp:629
 msgid "Toggle Reference Dimension"
 msgstr ""
 
-#: mouse.cpp:638
+#: mouse.cpp:635
 msgid "Other Supplementary Angle"
 msgstr ""
 
-#: mouse.cpp:643
+#: mouse.cpp:640
 msgid "Snap to Grid"
 msgstr ""
 
-#: mouse.cpp:652
+#: mouse.cpp:649
 msgid "Remove Spline Point"
 msgstr ""
 
-#: mouse.cpp:687
+#: mouse.cpp:684
 msgid "Add Spline Point"
 msgstr ""
 
-#: mouse.cpp:691
+#: mouse.cpp:688
 msgid "Cannot add spline point: maximum number of points reached."
 msgstr ""
 
-#: mouse.cpp:716
+#: mouse.cpp:713
 msgid "Toggle Construction"
 msgstr ""
 
-#: mouse.cpp:731
+#: mouse.cpp:729
 msgid "Delete Point-Coincident Constraint"
 msgstr ""
 
-#: mouse.cpp:750
+#: mouse.cpp:747
 msgid "Cut"
 msgstr ""
 
-#: mouse.cpp:752
+#: mouse.cpp:749
 msgid "Copy"
 msgstr ""
 
-#: mouse.cpp:756
+#: mouse.cpp:753
 msgid "Select All"
 msgstr ""
 
-#: mouse.cpp:761
+#: mouse.cpp:758
 msgid "Paste"
 msgstr ""
 
-#: mouse.cpp:763
+#: mouse.cpp:760
 msgid "Paste Transformed..."
 msgstr ""
 
-#: mouse.cpp:768
+#: mouse.cpp:765
 msgid "Delete"
 msgstr ""
 
-#: mouse.cpp:771
+#: mouse.cpp:768
 msgid "Unselect All"
 msgstr ""
 
-#: mouse.cpp:778
+#: mouse.cpp:775
 msgid "Unselect Hovered"
 msgstr ""
 
-#: mouse.cpp:787
+#: mouse.cpp:784
 msgid "Zoom to Fit"
 msgstr ""
 
-#: mouse.cpp:989 mouse.cpp:1276
+#: mouse.cpp:986 mouse.cpp:1274
 msgid "click next point of line, or press Esc"
 msgstr ""
 
-#: mouse.cpp:995
+#: mouse.cpp:992
 msgid "Can't draw rectangle in 3d; first, activate a workplane with Sketch -> In Workplane."
 msgstr ""
 
-#: mouse.cpp:1029
+#: mouse.cpp:1026
 msgid "click to place other corner of rectangle"
 msgstr ""
 
-#: mouse.cpp:1049
+#: mouse.cpp:1047
 msgid "click to set radius"
 msgstr ""
 
-#: mouse.cpp:1054
+#: mouse.cpp:1052
 msgid "Can't draw arc in 3d; first, activate a workplane with Sketch -> In Workplane."
 msgstr ""
 
-#: mouse.cpp:1073
+#: mouse.cpp:1071
 msgid "click to place point"
 msgstr ""
 
-#: mouse.cpp:1089
+#: mouse.cpp:1087
 msgid "click next point of cubic, or press Esc"
 msgstr ""
 
-#: mouse.cpp:1094
+#: mouse.cpp:1092
 msgid "Sketching in a workplane already; sketch in 3d before creating new workplane."
 msgstr ""
 
-#: mouse.cpp:1110
+#: mouse.cpp:1108
 msgid "Can't draw text in 3d; first, activate a workplane with Sketch -> In Workplane."
 msgstr ""
 
-#: mouse.cpp:1127
+#: mouse.cpp:1125
 msgid "click to place bottom right of text"
 msgstr ""
 
-#: mouse.cpp:1133
+#: mouse.cpp:1131
 msgid "Can't draw image in 3d; first, activate a workplane with Sketch -> In Workplane."
 msgstr ""
 
-#: mouse.cpp:1160
-msgid "NEW COMMENT -- DOUBLE-CLICK TO EDIT"
+#: platform/gui.cpp:85 platform/gui.cpp:90 solvespace.cpp:553
+msgctxt "file-type"
+msgid "SolveSpace models"
 msgstr ""
 
-#: platform/gui.cpp:85 platform/gui.cpp:89 solvespace.cpp:511
+#: platform/gui.cpp:89
 msgctxt "file-type"
-msgid "SolveSpace models"
+msgid "ALL"
 msgstr ""
 
-#: platform/gui.cpp:90
+#: platform/gui.cpp:91
 msgctxt "file-type"
 msgid "IDF circuit board"
 msgstr ""
 
-#: platform/gui.cpp:94
+#: platform/gui.cpp:92
+msgctxt "file-type"
+msgid "STL triangle mesh"
+msgstr ""
+
+#: platform/gui.cpp:96
 msgctxt "file-type"
 msgid "PNG image"
 msgstr ""
 
-#: platform/gui.cpp:98
+#: platform/gui.cpp:100
 msgctxt "file-type"
 msgid "STL mesh"
 msgstr ""
 
-#: platform/gui.cpp:99
+#: platform/gui.cpp:101
 msgctxt "file-type"
 msgid "Wavefront OBJ mesh"
 msgstr ""
 
-#: platform/gui.cpp:100
+#: platform/gui.cpp:102
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, with viewer"
 msgstr ""
 
-#: platform/gui.cpp:101
+#: platform/gui.cpp:103
 msgctxt "file-type"
 msgid "Three.js-compatible mesh, mesh only"
 msgstr ""
 
-#: platform/gui.cpp:102
+#: platform/gui.cpp:104
 msgctxt "file-type"
 msgid "VRML text file"
 msgstr ""
 
-#: platform/gui.cpp:106 platform/gui.cpp:113 platform/gui.cpp:120
+#: platform/gui.cpp:108 platform/gui.cpp:115 platform/gui.cpp:122
 msgctxt "file-type"
 msgid "STEP file"
 msgstr ""
 
-#: platform/gui.cpp:110
+#: platform/gui.cpp:112
 msgctxt "file-type"
 msgid "PDF file"
 msgstr ""
 
-#: platform/gui.cpp:111
+#: platform/gui.cpp:113
 msgctxt "file-type"
 msgid "Encapsulated PostScript"
 msgstr ""
 
-#: platform/gui.cpp:112
+#: platform/gui.cpp:114
 msgctxt "file-type"
 msgid "Scalable Vector Graphics"
 msgstr ""
 
-#: platform/gui.cpp:114 platform/gui.cpp:121
+#: platform/gui.cpp:116 platform/gui.cpp:123
 msgctxt "file-type"
 msgid "DXF file (AutoCAD 2007)"
 msgstr ""
 
-#: platform/gui.cpp:115
+#: platform/gui.cpp:117
 msgctxt "file-type"
 msgid "HPGL file"
 msgstr ""
 
-#: platform/gui.cpp:116
+#: platform/gui.cpp:118
 msgctxt "file-type"
 msgid "G Code"
 msgstr ""
 
-#: platform/gui.cpp:125
+#: platform/gui.cpp:127
 msgctxt "file-type"
 msgid "AutoCAD DXF and DWG files"
 msgstr ""
 
-#: platform/gui.cpp:129
+#: platform/gui.cpp:131
 msgctxt "file-type"
 msgid "Comma-separated values"
 msgstr ""
 
-#: platform/guigtk.cpp:1321 platform/guimac.mm:1363 platform/guiwin.cpp:1630
+#: platform/guigtk.cpp:1382 platform/guimac.mm:1509 platform/guiwin.cpp:1641
 msgid "untitled"
 msgstr ""
 
-#: platform/guigtk.cpp:1332 platform/guigtk.cpp:1365 platform/guimac.mm:1321
-#: platform/guiwin.cpp:1573
+#: platform/guigtk.cpp:1393 platform/guigtk.cpp:1426 platform/guimac.mm:1467
+#: platform/guiwin.cpp:1639
 msgctxt "title"
 msgid "Save File"
 msgstr ""
 
-#: platform/guigtk.cpp:1333 platform/guigtk.cpp:1366 platform/guimac.mm:1304
-#: platform/guiwin.cpp:1575
+#: platform/guigtk.cpp:1394 platform/guigtk.cpp:1427 platform/guimac.mm:1450
+#: platform/guiwin.cpp:1645
 msgctxt "title"
 msgid "Open File"
 msgstr ""
 
-#: platform/guigtk.cpp:1336 platform/guigtk.cpp:1372
+#: platform/guigtk.cpp:1397 platform/guigtk.cpp:1433
 msgctxt "button"
 msgid "_Cancel"
 msgstr ""
 
-#: platform/guigtk.cpp:1337 platform/guigtk.cpp:1370
+#: platform/guigtk.cpp:1398 platform/guigtk.cpp:1431
 msgctxt "button"
 msgid "_Save"
 msgstr ""
 
-#: platform/guigtk.cpp:1338 platform/guigtk.cpp:1371
+#: platform/guigtk.cpp:1399 platform/guigtk.cpp:1432
 msgctxt "button"
 msgid "_Open"
 msgstr ""
 
-#: solvespace.cpp:169
+#: solvespace.cpp:171
 msgctxt "title"
 msgid "Autosave Available"
 msgstr ""
 
-#: solvespace.cpp:170
+#: solvespace.cpp:172
 msgctxt "dialog"
 msgid "An autosave file is available for this sketch."
 msgstr ""
 
-#: solvespace.cpp:171
+#: solvespace.cpp:173
 msgctxt "dialog"
 msgid "Do you want to load the autosave file instead?"
 msgstr ""
 
-#: solvespace.cpp:172
+#: solvespace.cpp:174
 msgctxt "button"
 msgid "&Load autosave"
 msgstr ""
 
-#: solvespace.cpp:174
+#: solvespace.cpp:176
 msgctxt "button"
 msgid "Do&n't Load"
 msgstr ""
 
-#: solvespace.cpp:557
+#: solvespace.cpp:599
 msgctxt "title"
 msgid "Modified File"
 msgstr ""
 
-#: solvespace.cpp:559
+#: solvespace.cpp:601
 #, c-format
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the sketch “%s”?"
 msgstr ""
 
-#: solvespace.cpp:562
+#: solvespace.cpp:604
 msgctxt "dialog"
 msgid "Do you want to save the changes you made to the new sketch?"
 msgstr ""
 
-#: solvespace.cpp:565
+#: solvespace.cpp:607
 msgctxt "dialog"
 msgid "Your changes will be lost if you don't save them."
 msgstr ""
 
-#: solvespace.cpp:566
+#: solvespace.cpp:608
 msgctxt "button"
 msgid "&Save"
 msgstr ""
 
-#: solvespace.cpp:568
+#: solvespace.cpp:610
 msgctxt "button"
 msgid "Do&n't Save"
 msgstr ""
 
-#: solvespace.cpp:589
+#: solvespace.cpp:631
 msgctxt "title"
 msgid "(new sketch)"
 msgstr ""
 
-#: solvespace.cpp:596
+#: solvespace.cpp:638
 msgctxt "title"
 msgid "Property Browser"
 msgstr ""
 
-#: solvespace.cpp:658
+#: solvespace.cpp:700
 msgid ""
 "Constraints are currently shown, and will be exported in the toolpath. This is probably not what "
 "you want; hide them by clicking the link at the top of the text window."
 msgstr ""
 
-#: solvespace.cpp:730
+#: solvespace.cpp:772
 #, c-format
 msgid "Can't identify file type from file extension of filename '%s'; try .dxf or .dwg."
 msgstr ""
 
-#: solvespace.cpp:778
+#: solvespace.cpp:824
 msgid "Constraint must have a label, and must not be a reference dimension."
 msgstr ""
 
-#: solvespace.cpp:782
+#: solvespace.cpp:828
 msgid "Bad selection for step dimension; select a constraint."
 msgstr ""
 
-#: solvespace.cpp:806
+#: solvespace.cpp:852
 msgid "The assembly does not interfere, good."
 msgstr ""
 
-#: solvespace.cpp:822
+#: solvespace.cpp:868
 #, c-format
 msgid ""
 "The volume of the solid model is:\n"
@@ -1567,7 +1622,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:831
+#: solvespace.cpp:877
 #, c-format
 msgid ""
 "\n"
@@ -1576,7 +1631,7 @@ msgid ""
 "    %s"
 msgstr ""
 
-#: solvespace.cpp:836
+#: solvespace.cpp:882
 msgid ""
 "\n"
 "\n"
@@ -1584,7 +1639,7 @@ msgid ""
 "This introduces error, typically of around 1%."
 msgstr ""
 
-#: solvespace.cpp:851
+#: solvespace.cpp:897
 #, c-format
 msgid ""
 "The surface area of the selected faces is:\n"
@@ -1595,13 +1650,13 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:860
+#: solvespace.cpp:906
 msgid ""
 "This group does not contain a correctly-formed 2d closed area. It is open, not coplanar, or self-"
 "intersecting."
 msgstr ""
 
-#: solvespace.cpp:872
+#: solvespace.cpp:918
 #, c-format
 msgid ""
 "The area of the region sketched in this group is:\n"
@@ -1612,7 +1667,7 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:892
+#: solvespace.cpp:938
 #, c-format
 msgid ""
 "The total length of the selected entities is:\n"
@@ -1623,36 +1678,36 @@ msgid ""
 "This introduces error, typically of around 1%%."
 msgstr ""
 
-#: solvespace.cpp:898
+#: solvespace.cpp:944
 msgid "Bad selection for perimeter; select line segments, arcs, and curves."
 msgstr ""
 
-#: solvespace.cpp:914
+#: solvespace.cpp:960
 msgid "Bad selection for trace; select a single point."
 msgstr ""
 
-#: solvespace.cpp:941
+#: solvespace.cpp:987
 #, c-format
 msgid "Couldn't write to '%s'"
 msgstr ""
 
-#: solvespace.cpp:971
+#: solvespace.cpp:1017
 msgid "The mesh is self-intersecting (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:972
+#: solvespace.cpp:1018
 msgid "The mesh is not self-intersecting (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:974
+#: solvespace.cpp:1020
 msgid "The mesh has naked edges (NOT okay, invalid)."
 msgstr ""
 
-#: solvespace.cpp:975
+#: solvespace.cpp:1021
 msgid "The mesh is watertight (okay, valid)."
 msgstr ""
 
-#: solvespace.cpp:978
+#: solvespace.cpp:1024
 #, c-format
 msgid ""
 "\n"
@@ -1660,7 +1715,7 @@ msgid ""
 "The model contains %d triangles, from %d surfaces."
 msgstr ""
 
-#: solvespace.cpp:982
+#: solvespace.cpp:1028
 #, c-format
 msgid ""
 "%s\n"
@@ -1670,7 +1725,7 @@ msgid ""
 "Zero problematic edges, good.%s"
 msgstr ""
 
-#: solvespace.cpp:985
+#: solvespace.cpp:1031
 #, c-format
 msgid ""
 "%s\n"
@@ -1680,7 +1735,7 @@ msgid ""
 "%d problematic edges, bad.%s"
 msgstr ""
 
-#: solvespace.cpp:998
+#: solvespace.cpp:1044
 #, c-format
 msgid ""
 "This is SolveSpace version %s.\n"
@@ -1697,33 +1752,33 @@ msgid ""
 "© 2008-%d Jonathan Westhues and other authors.\n"
 msgstr ""
 
-#: style.cpp:166
+#: style.cpp:185
 msgid ""
 "Can't assign style to an entity that's derived from another entity; try assigning a style to this "
 "entity's parent."
 msgstr ""
 
-#: style.cpp:665
+#: style.cpp:735
 msgid "Style name cannot be empty"
 msgstr ""
 
-#: textscreens.cpp:741
+#: textscreens.cpp:791
 msgid "Can't repeat fewer than 1 time."
 msgstr ""
 
-#: textscreens.cpp:745
+#: textscreens.cpp:795
 msgid "Can't repeat more than 999 times."
 msgstr ""
 
-#: textscreens.cpp:770
+#: textscreens.cpp:820
 msgid "Group name cannot be empty"
 msgstr ""
 
-#: textscreens.cpp:813
+#: textscreens.cpp:872
 msgid "Opacity must be between zero and one."
 msgstr ""
 
-#: textscreens.cpp:848
+#: textscreens.cpp:907
 msgid "Radius cannot be zero or negative."
 msgstr ""
 
@@ -1878,10 +1933,10 @@ msgctxt "button"
 msgid "&OK"
 msgstr ""
 
-#: view.cpp:78
+#: view.cpp:127
 msgid "Scale cannot be zero or negative."
 msgstr ""
 
-#: view.cpp:90 view.cpp:99
+#: view.cpp:139 view.cpp:148
 msgid "Bad format: specify x, y, z"
 msgstr ""
index e141aceec49a5b301da2d83f423499f313fdfa50..ca74fd52081e5c4883892c2865c638f2416a4f3c 100644 (file)
@@ -470,9 +470,9 @@ solvespace = function(obj, params) {
         changeBasis.makeBasis(camera.right, camera.up, n);
 
         for (var i = 0; i < 2; i++) {
-            var newLightPos = changeBasis.applyToVector3Array(
-                [obj.lights.d[i].direction[0], obj.lights.d[i].direction[1],
-                    obj.lights.d[i].direction[2]]);
+            var newLightPos = new THREE.Vector3(obj.lights.d[i].direction[0],
+                obj.lights.d[i].direction[1],
+                obj.lights.d[i].direction[2]).applyMatrix4(changeBasis);
             directionalLightArray[i].position.set(newLightPos[0],
                 newLightPos[1], newLightPos[2]);
         }
@@ -515,7 +515,7 @@ solvespace = function(obj, params) {
         }
 
         geometry.computeBoundingSphere();
-        return new THREE.Mesh(geometry, new THREE.MultiMaterial(materialList));
+        return new THREE.Mesh(geometry, materialList);
     }
 
     function createEdges(meshObj) {
diff --git a/res/threejs/three-r111.min.js.gz b/res/threejs/three-r111.min.js.gz
new file mode 100644 (file)
index 0000000..7e6f57f
Binary files /dev/null and b/res/threejs/three-r111.min.js.gz differ
index e6e90056ae549262ea172c23cb7deff2f5bb1b2f..1aba0522da2806df10da84a310c3f1bb558c16b1 100644 (file)
@@ -1,6 +1,6 @@
 1 VERSIONINFO
-FILEVERSION     ${solvespace_VERSION_MAJOR},${solvespace_VERSION_MINOR},0,0
-PRODUCTVERSION  ${solvespace_VERSION_MAJOR},${solvespace_VERSION_MINOR},0,0
+FILEVERSION     ${PROJECT_VERSION_MAJOR},${PROJECT_VERSION_MINOR},0,0
+PRODUCTVERSION  ${PROJECT_VERSION_MAJOR},${PROJECT_VERSION_MINOR},0,0
 FILEFLAGSMASK   0
 FILEFLAGS       0
 FILEOS          VOS_NT_WINDOWS32
@@ -13,12 +13,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName",      "The SolveSpace authors"
             VALUE "ProductName",      "SolveSpace"
-            VALUE "ProductVersion",   "${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}~${solvespace_GIT_HASH}"
+            VALUE "ProductVersion",   "${PROJECT_VERSION}~${solvespace_GIT_HASH}"
             VALUE "FileDescription",  "SolveSpace, a parametric 2d/3d CAD"
-            VALUE "FileVersion",      "${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}~${solvespace_GIT_HASH}"
+            VALUE "FileVersion",      "${PROJECT_VERSION}~${solvespace_GIT_HASH}"
             VALUE "OriginalFilename", "solvespace.exe"
             VALUE "InternalName",     "solvespace"
-            VALUE "LegalCopyright",   "(c) 2008-2021 Jonathan Westhues and other authors"
+            VALUE "LegalCopyright",   "(c) 2008-2022 Jonathan Westhues and other authors"
         END
     END
 
index 45dab944f649c63d49914b535debf2d4a562c498..0c0277eef69ec40b4d60539d0c8be25041646b9e 100644 (file)
@@ -19,32 +19,63 @@ endif()
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
                ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
+# solvespace dependencies
+add_library(slvs_deps INTERFACE)
+target_include_directories(slvs_deps INTERFACE SYSTEM
+    ${OPENGL_INCLUDE_DIR}
+    ${ZLIB_INCLUDE_DIR}
+    ${PNG_PNG_INCLUDE_DIR}
+    ${FREETYPE_INCLUDE_DIRS}
+    ${CAIRO_INCLUDE_DIRS}
+    ${MIMALLOC_INCLUDE_DIR}
+    ${EIGEN3_INCLUDE_DIRS})
+target_link_libraries(slvs_deps INTERFACE
+    dxfrw
+    ${ZLIB_LIBRARY}
+    ${PNG_LIBRARY}
+    ${FREETYPE_LIBRARY}
+    ${CAIRO_LIBRARIES}
+    mimalloc-static)
+
+if(Backtrace_FOUND)
+    target_include_directories(slvs_deps INTERFACE SYSTEM
+        ${Backtrace_INCLUDE_DIRS})
+    target_link_libraries(slvs_deps INTERFACE
+        ${Backtrace_LIBRARY})
+endif()
+
+if(SPACEWARE_FOUND)
+    target_include_directories(slvs_deps INTERFACE SYSTEM
+        ${SPACEWARE_INCLUDE_DIR})
+    target_link_libraries(slvs_deps INTERFACE
+        ${SPACEWARE_LIBRARIES})
+endif()
+
+if(ENABLE_OPENMP)
+    target_link_libraries(slvs_deps INTERFACE slvs_openmp)
+endif()
+
+target_compile_options(slvs_deps
+    INTERFACE ${COVERAGE_FLAGS})
+
 # platform utilities
 
 if(APPLE)
-    set(util_LIBRARIES
+    target_link_libraries(slvs_deps INTERFACE
         ${APPKIT_LIBRARY})
 endif()
 
 # libslvs
-
-set(libslvs_SOURCES
+add_library(slvs SHARED
+    solvespace.h
+    platform/platform.h
     util.cpp
     entity.cpp
     expr.cpp
     constraint.cpp
     constrainteq.cpp
     system.cpp
-    platform/platform.cpp)
-
-set(libslvs_HEADERS
-    solvespace.h
-    platform/platform.h)
-
-add_library(slvs SHARED
-    ${libslvs_SOURCES}
-    ${libslvs_HEADERS}
-    ${util_SOURCES}
+    platform/platform.cpp
     lib.cpp)
 
 target_compile_definitions(slvs
@@ -53,16 +84,11 @@ target_compile_definitions(slvs
 target_include_directories(slvs
     PUBLIC ${CMAKE_SOURCE_DIR}/include)
 
-target_link_libraries(slvs
-    ${util_LIBRARIES}
-    mimalloc-static)
-
-add_dependencies(slvs
-    mimalloc-static)
+target_link_libraries(slvs PRIVATE slvs_deps)
 
 set_target_properties(slvs PROPERTIES
     PUBLIC_HEADER ${CMAKE_SOURCE_DIR}/include/slvs.h
-    VERSION ${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}
+    VERSION ${PROJECT_VERSION}
     SOVERSION 1)
 
 if(NOT WIN32)
@@ -72,69 +98,6 @@ if(NOT WIN32)
         PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
 endif()
 
-# solvespace dependencies
-
-include_directories(
-    ${OPENGL_INCLUDE_DIR}
-    ${ZLIB_INCLUDE_DIR}
-    ${PNG_PNG_INCLUDE_DIR}
-    ${FREETYPE_INCLUDE_DIRS}
-    ${CAIRO_INCLUDE_DIRS}
-    ${MIMALLOC_INCLUDE_DIR}
-    ${OpenMP_CXX_INCLUDE_DIRS})
-
-if(Backtrace_FOUND)
-    include_directories(
-        ${Backtrace_INCLUDE_DIRS})
-endif()
-
-if(SPACEWARE_FOUND)
-    include_directories(
-        ${SPACEWARE_INCLUDE_DIR})
-endif()
-
-if(OPENGL STREQUAL 3)
-    set(gl_SOURCES
-        render/gl3shader.cpp
-        render/rendergl3.cpp)
-elseif(OPENGL STREQUAL 1)
-    set(gl_SOURCES
-        render/rendergl1.cpp)
-else()
-    message(FATAL_ERROR "Unsupported OpenGL version ${OPENGL}")
-endif()
-
-set(platform_SOURCES
-    ${gl_SOURCES}
-    platform/entrygui.cpp)
-
-if(WIN32)
-    list(APPEND platform_SOURCES
-        platform/guiwin.cpp)
-
-    set(platform_LIBRARIES
-        comctl32
-        ${SPACEWARE_LIBRARIES})
-elseif(APPLE)
-    add_compile_options(
-        -fobjc-arc)
-
-    list(APPEND platform_SOURCES
-        platform/guimac.mm)
-else()
-    list(APPEND platform_SOURCES
-        platform/guigtk.cpp)
-
-    set(platform_LIBRARIES
-        ${SPACEWARE_LIBRARIES})
-
-    foreach(pkg_config_lib GTKMM JSONC FONTCONFIG)
-        include_directories(${${pkg_config_lib}_INCLUDE_DIRS})
-        link_directories(${${pkg_config_lib}_LIBRARY_DIRS})
-        list(APPEND platform_LIBRARIES ${${pkg_config_lib}_LIBRARIES})
-    endforeach()
-endif()
-
 set(every_platform_SOURCES
     platform/guiwin.cpp
     platform/guigtk.cpp
@@ -142,7 +105,10 @@ set(every_platform_SOURCES
 
 # solvespace library
 
-set(solvespace_core_HEADERS
+set(solvespace_core_gl_SOURCES
+    solvespace.cpp)
+
+add_library(solvespace-core STATIC
     dsc.h
     expr.h
     polygon.h
@@ -152,9 +118,7 @@ set(solvespace_core_HEADERS
     platform/platform.h
     render/render.h
     render/gl3shader.h
-    srf/surface.h)
-
-set(solvespace_core_SOURCES
+    srf/surface.h
     bsp.cpp
     clipboard.cpp
     confscreen.cpp
@@ -176,6 +140,7 @@ set(solvespace_core_SOURCES
     groupmesh.cpp
     importdxf.cpp
     importidf.cpp
+    importmesh.cpp
     mesh.cpp
     modify.cpp
     mouse.cpp
@@ -201,44 +166,19 @@ set(solvespace_core_SOURCES
     srf/merge.cpp
     srf/ratpoly.cpp
     srf/raycast.cpp
+    srf/shell.cpp
     srf/surface.cpp
     srf/surfinter.cpp
     srf/triangulate.cpp)
 
-set(solvespace_core_gl_SOURCES
-    solvespace.cpp)
-
-add_library(solvespace-core STATIC
-    ${util_SOURCES}
-    ${solvespace_core_HEADERS}
-    ${solvespace_core_SOURCES})
-
-add_dependencies(solvespace-core
-    mimalloc-static)
-
-target_link_libraries(solvespace-core
-    ${OpenMP_CXX_LIBRARIES}
-    dxfrw
-    ${util_LIBRARIES}
-    ${ZLIB_LIBRARY}
-    ${PNG_LIBRARY}
-    ${FREETYPE_LIBRARY}
-    mimalloc-static)
-
-if(Backtrace_FOUND)
-    target_link_libraries(solvespace-core
-        ${Backtrace_LIBRARY})
-endif()
-
-target_compile_options(solvespace-core
-    PRIVATE ${COVERAGE_FLAGS})
+target_link_libraries(solvespace-core PUBLIC slvs_deps)
 
 # solvespace translations
 
 if(HAVE_GETTEXT)
+    get_target_property(solvespace_core_SOURCES solvespace-core SOURCES)
     set(inputs
         ${solvespace_core_SOURCES}
-        ${solvespace_core_HEADERS}
         ${every_platform_SOURCES}
         ${solvespace_core_gl_SOURCES})
 
@@ -265,7 +205,7 @@ if(HAVE_GETTEXT)
                 --keyword --keyword=_ --keyword=N_ --keyword=C_:2,1c --keyword=CN_:2,1c
                 --force-po --width=100 --sort-by-file
                 --package-name=SolveSpace
-                --package-version=${solvespace_VERSION_MAJOR}.${solvespace_VERSION_MINOR}
+                --package-version=${PROJECT_VERSION}
                 "--copyright-holder=the PACKAGE authors"
                 --msgid-bugs-address=whitequark@whitequark.org
                 --from-code=utf-8 --output=${gen_output_pot} ${inputs}
@@ -321,49 +261,86 @@ endif()
 if(ENABLE_GUI)
     add_executable(solvespace WIN32 MACOSX_BUNDLE
         ${solvespace_core_gl_SOURCES}
-        ${platform_SOURCES}
+        platform/entrygui.cpp
         $<TARGET_PROPERTY:resources,EXTRA_SOURCES>)
 
     add_dependencies(solvespace
         resources)
 
     target_link_libraries(solvespace
+        PRIVATE
         solvespace-core
-        ${OPENGL_LIBRARIES}
-        ${platform_LIBRARIES}
-        ${COVERAGE_LIBRARY})
+        ${OPENGL_LIBRARIES})
+
+    # OpenGL version
+    if(OPENGL STREQUAL 3)
+        target_sources(solvespace PRIVATE
+            render/gl3shader.cpp
+            render/rendergl3.cpp)
+    elseif(OPENGL STREQUAL 1)
+        target_sources(solvespace PRIVATE
+            render/rendergl1.cpp)
+    else()
+        message(FATAL_ERROR "Unsupported OpenGL version ${OPENGL}")
+    endif()
+
+    # Platform-specific
+    if(WIN32)
+        target_sources(solvespace PRIVATE
+            platform/guiwin.cpp)
+
+        target_link_libraries(solvespace PRIVATE comctl32)
+    elseif(APPLE)
+        target_compile_options(solvespace PRIVATE -fobjc-arc)
+        target_compile_definitions(solvespace PRIVATE GL_SILENCE_DEPRECATION)
+
+        target_sources(solvespace PRIVATE
+            platform/guimac.mm)
+        set_target_properties(solvespace PROPERTIES
+            OUTPUT_NAME SolveSpace
+            XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES"
+            XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.solvespace"
+            RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+    else()
+        target_sources(solvespace PRIVATE
+            platform/guigtk.cpp)
+
+        target_include_directories(solvespace PRIVATE SYSTEM
+            ${GTKMM_INCLUDE_DIRS}
+            ${JSONC_INCLUDE_DIRS}
+            ${FONTCONFIG_INCLUDE_DIRS})
+        target_link_directories(solvespace PRIVATE
+            ${GTKMM_LIBRARY_DIRS}
+            ${JSONC_LIBRARY_DIRS}
+            ${FONTCONFIG_LIBRARY_DIRS})
+        target_link_libraries(solvespace PRIVATE
+            ${GTKMM_LIBRARIES}
+            ${JSONC_LIBRARIES}
+            ${FONTCONFIG_LIBRARIES})
+    endif()
 
     if(MSVC)
         set_target_properties(solvespace PROPERTIES
             LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /INCREMENTAL:NO /OPT:REF")
-    elseif(APPLE)
-        set_target_properties(solvespace PROPERTIES
-            OUTPUT_NAME SolveSpace)
     endif()
 endif()
 
 # solvespace headless library
 
-set(headless_SOURCES
-    platform/guinone.cpp
-    render/rendercairo.cpp)
-
 add_library(solvespace-headless STATIC EXCLUDE_FROM_ALL
     ${solvespace_core_gl_SOURCES}
-    ${headless_SOURCES})
+    platform/guinone.cpp
+    render/rendercairo.cpp)
 
 target_compile_definitions(solvespace-headless
-    PRIVATE -DHEADLESS)
+    PRIVATE HEADLESS)
 
 target_include_directories(solvespace-headless
     INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
 
 target_link_libraries(solvespace-headless
-    solvespace-core
-    ${CAIRO_LIBRARIES})
-
-target_compile_options(solvespace-headless
-    PRIVATE ${COVERAGE_FLAGS})
+    PRIVATE
+    solvespace-core)
 
 # solvespace command-line executable
 
@@ -401,17 +378,30 @@ endif()
 # solvespace macOS package
 
 if(APPLE)
-    set(bundle     SolveSpace)
-    set(bundle_bin ${EXECUTABLE_OUTPUT_PATH}/${bundle}.app/Contents/MacOS)
-    set(bundle_resources ${EXECUTABLE_OUTPUT_PATH}/${bundle}.app/Contents/Resources/lib)
-    execute_process(
-        COMMAND mkdir -p ${bundle_resources}
-        COMMAND cp -p /usr/local/opt/libomp/lib/libomp.dylib ${bundle_resources}/libomp.dylib
-    )
-    add_custom_command(TARGET solvespace POST_BUILD
-        COMMAND ${CMAKE_COMMAND} -E make_directory ${bundle_bin}
-        COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:solvespace-cli> ${bundle_bin}
-        COMMAND install_name_tool -change /usr/local/opt/libomp/lib/libomp.dylib "@executable_path/../Resources/lib/libomp.dylib" ${bundle_bin}/${bundle}
-        COMMENT "Bundling executable solvespace-cli"
-        VERBATIM)
+    set(LIBOMP_LIB_PATH ${OpenMP_CXX_INCLUDE_DIRS}/../lib/libomp.dylib)
+    set(LIBOMP_LINK_PATH "@executable_path/../Resources/libomp.dylib")
+    set(LIBOMP_LINK_PATH_UTILS "@executable_path/SolveSpace.app/Contents/Resources/libomp.dylib")
+    if(ENABLE_GUI)
+        add_custom_command(TARGET solvespace POST_BUILD
+            COMMAND cp -r ${CMAKE_BINARY_DIR}/Resources $<TARGET_BUNDLE_CONTENT_DIR:solvespace>
+        )
+        if(ENABLE_OPENMP)
+            execute_process(COMMAND install_name_tool -id ${LIBOMP_LINK_PATH} ${LIBOMP_LIB_PATH})
+            message("FROM " ${${LIBOMP_LIB_PATH}} "TO" $<TARGET_BUNDLE_CONTENT_DIR:solvespace>/Resources/libomp.dylib)
+            add_custom_command(TARGET solvespace POST_BUILD
+                COMMAND ${CMAKE_COMMAND} -E copy ${LIBOMP_LIB_PATH} $<TARGET_BUNDLE_CONTENT_DIR:solvespace>/Resources/libomp.dylib
+                COMMAND install_name_tool -change ${LIBOMP_LINK_PATH} ${LIBOMP_LINK_PATH_UTILS} $<TARGET_FILE:solvespace-debugtool>
+            )
+        endif()
+    endif()
+    if(ENABLE_TESTS AND ENABLE_OPENMP)
+        add_custom_command(TARGET solvespace POST_BUILD
+            COMMAND install_name_tool -change ${LIBOMP_LINK_PATH} ${LIBOMP_LINK_PATH_UTILS} $<TARGET_FILE:solvespace-testsuite>)
+    endif()
+    if(ENABLE_CLI)
+        add_custom_command(TARGET solvespace POST_BUILD
+            COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:solvespace-cli> $<TARGET_FILE_DIR:solvespace>
+            COMMENT "Bundling executable solvespace-cli"
+            VERBATIM)
+    endif()
 endif()
index d43ec4582362404fbe30c1b0d0c8b17f1ded992e..69a624c3721d86d41fdbc93cb86af9902f04bfeb 100644 (file)
@@ -138,18 +138,17 @@ void GraphicsWindow::CopySelection() {
         }
     }
 
-    Constraint *c;
-    for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
-        if(!SS.clipboard.ContainsEntity(c->ptA) ||
-           !SS.clipboard.ContainsEntity(c->ptB) ||
-           !SS.clipboard.ContainsEntity(c->entityA) ||
-           !SS.clipboard.ContainsEntity(c->entityB) ||
-           !SS.clipboard.ContainsEntity(c->entityC) ||
-           !SS.clipboard.ContainsEntity(c->entityD) ||
-           c->type == Constraint::Type::COMMENT) {
+    for(Constraint &c : SK.constraint) {
+        if(!SS.clipboard.ContainsEntity(c.ptA) ||
+           !SS.clipboard.ContainsEntity(c.ptB) ||
+           !SS.clipboard.ContainsEntity(c.entityA) ||
+           !SS.clipboard.ContainsEntity(c.entityB) ||
+           !SS.clipboard.ContainsEntity(c.entityC) ||
+           !SS.clipboard.ContainsEntity(c.entityD) ||
+           c.type == Constraint::Type::COMMENT) {
             continue;
         }
-        SS.clipboard.c.Add(c);
+        SS.clipboard.c.Add(&c);
     }
 }
 
@@ -282,7 +281,7 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
             }
             case Constraint::Type::HORIZONTAL:
             case Constraint::Type::VERTICAL:
-                // When rotating 90 or 270 degrees, swap the vertical / horizontal constaints
+                // When rotating 90 or 270 degrees, swap the vertical / horizontal constraints
                 if (EXACT(fmod(theta + (PI/2), PI) == 0)) {
                     if(c.type == Constraint::Type::HORIZONTAL) {
                         c.type = Constraint::Type::VERTICAL;
index 144c46d04f244c60c0cec9059c551f82b04a9100..187b9cbce4af2118bc11baa6b5842661c3206547 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef SOLVESPACE_CONFIG_H
 #define SOLVESPACE_CONFIG_H
 
-#define PACKAGE_VERSION "@solvespace_VERSION_MAJOR@.@solvespace_VERSION_MINOR@~@solvespace_GIT_HASH@"
+#define PACKAGE_VERSION "@PROJECT_VERSION@~@solvespace_GIT_HASH@"
+#define GIT_HASH_URL "https://github.com/solvespace/solvespace/commit/@solvespace_GIT_HASH@"
 
 /* Non-OS X *nix only */
 #define UNIX_DATADIR "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATAROOTDIR@/solvespace"
index c7e2815a0bf99b55f1a08f0072a0dd82c9978e08..1e2e82a6914b34e2dedb3322e602f1b20dddbc85 100644 (file)
@@ -9,24 +9,6 @@
 #include <omp.h>
 #endif
 
-void TextWindow::ScreenChangeLightDirection(int link, uint32_t v) {
-    SS.TW.ShowEditControl(8, ssprintf("%.2f, %.2f, %.2f", CO(SS.lightDir[v])));
-    SS.TW.edit.meaning = Edit::LIGHT_DIRECTION;
-    SS.TW.edit.i = v;
-}
-
-void TextWindow::ScreenChangeLightIntensity(int link, uint32_t v) {
-    SS.TW.ShowEditControl(31, ssprintf("%.2f", SS.lightIntensity[v]));
-    SS.TW.edit.meaning = Edit::LIGHT_INTENSITY;
-    SS.TW.edit.i = v;
-}
-
-void TextWindow::ScreenChangeLightAmbient(int link, uint32_t v) {
-    SS.TW.ShowEditControl(31, ssprintf("%.2f", SS.ambientIntensity));
-    SS.TW.edit.meaning = Edit::LIGHT_AMBIENT;
-    SS.TW.edit.i = 0;
-}
-
 void TextWindow::ScreenChangeColor(int link, uint32_t v) {
     SS.TW.ShowEditControlWithColorPicker(13, SS.modelColor[v]);
 
@@ -58,13 +40,8 @@ void TextWindow::ScreenChangeExportMaxSegments(int link, uint32_t v) {
     SS.TW.edit.i = 1;
 }
 
-void TextWindow::ScreenChangeCameraTangent(int link, uint32_t v) {
-    SS.TW.ShowEditControl(3, ssprintf("%.3f", 1000*SS.cameraTangent));
-    SS.TW.edit.meaning = Edit::CAMERA_TANGENT;
-}
-
 void TextWindow::ScreenChangeGridSpacing(int link, uint32_t v) {
-    SS.TW.ShowEditControl(3, SS.MmToString(SS.gridSpacing));
+    SS.TW.ShowEditControl(3, SS.MmToString(SS.gridSpacing, true));
     SS.TW.edit.meaning = Edit::GRID_SPACING;
 }
 
@@ -89,7 +66,7 @@ void TextWindow::ScreenChangeExportScale(int link, uint32_t v) {
 }
 
 void TextWindow::ScreenChangeExportOffset(int link, uint32_t v) {
-    SS.TW.ShowEditControl(3, SS.MmToString(SS.exportOffset));
+    SS.TW.ShowEditControl(3, SS.MmToString(SS.exportOffset, true));
     SS.TW.edit.meaning = Edit::EXPORT_OFFSET;
 }
 
@@ -171,7 +148,7 @@ void TextWindow::ScreenChangeCanvasSize(int link, uint32_t v) {
     }
     int col = 13;
     if(v < 10) col = 11;
-    SS.TW.ShowEditControl(col, SS.MmToString(d));
+    SS.TW.ShowEditControl(col, SS.MmToString(d, true));
     SS.TW.edit.meaning = Edit::CANVAS_SIZE;
     SS.TW.edit.i = v;
 }
@@ -181,7 +158,12 @@ void TextWindow::ScreenChangeGCodeParameter(int link, uint32_t v) {
     switch(link) {
         case 'd':
             SS.TW.edit.meaning = Edit::G_CODE_DEPTH;
-            buf += SS.MmToString(SS.gCode.depth);
+            buf += SS.MmToString(SS.gCode.depth, true);
+            break;
+
+        case 'h':
+            SS.TW.edit.meaning = Edit::G_CODE_SAFE_HEIGHT;
+            buf += SS.MmToString(SS.gCode.safeHeight, true);
             break;
 
         case 's':
@@ -191,12 +173,12 @@ void TextWindow::ScreenChangeGCodeParameter(int link, uint32_t v) {
 
         case 'F':
             SS.TW.edit.meaning = Edit::G_CODE_FEED;
-            buf += SS.MmToString(SS.gCode.feed);
+            buf += SS.MmToString(SS.gCode.feed, true);
             break;
 
         case 'P':
             SS.TW.edit.meaning = Edit::G_CODE_PLUNGE_FEED;
-            buf += SS.MmToString(SS.gCode.plungeFeed);
+            buf += SS.MmToString(SS.gCode.plungeFeed, true);
             break;
     }
     SS.TW.ShowEditControl(14, buf);
@@ -227,20 +209,6 @@ void TextWindow::ShowConfiguration() {
             &ScreenChangeColor, i);
     }
 
-    Printf(false, "");
-    Printf(false, "%Ft light direction               intensity");
-    for(i = 0; i < 2; i++) {
-        Printf(false, "%Bp   #%d  (%2,%2,%2)%Fl%D%f%Ll[c]%E "
-                      "%2 %Fl%D%f%Ll[c]%E",
-            (i & 1) ? 'd' : 'a', i,
-            CO(SS.lightDir[i]), i, &ScreenChangeLightDirection,
-            SS.lightIntensity[i], i, &ScreenChangeLightIntensity);
-    }
-    Printf(false, "%Bp         ambient lighting     "
-                  "%2 %Fl%D%f%Ll[c]%E",
-            (i & 1) ? 'd' : 'a', i,
-        SS.ambientIntensity, &ScreenChangeLightAmbient);
-
     Printf(false, "");
     Printf(false, "%Ft chord tolerance (in percents)%E");
     Printf(false, "%Ba   %@ %% %Fl%Ll%f%D[change]%E; %@ mm, %d triangles",
@@ -262,11 +230,6 @@ void TextWindow::ShowConfiguration() {
         SS.exportMaxSegments,
         &ScreenChangeExportMaxSegments);
 
-    Printf(false, "");
-    Printf(false, "%Ft perspective factor (0 for parallel)%E");
-    Printf(false, "%Ba   %# %Fl%Ll%f%D[change]%E",
-        SS.cameraTangent*1000,
-        &ScreenChangeCameraTangent, 0);
     Printf(false, "%Ft snap grid spacing%E");
     Printf(false, "%Ba   %s %Fl%Ll%f%D[change]%E",
         SS.MmToString(SS.gridSpacing).c_str(),
@@ -461,6 +424,11 @@ bool TextWindow::EditControlDoneForConfiguration(const std::string &s) {
             SS.GW.Invalidate();
             break;
         }
+        case Edit::EXPLODE_DISTANCE: {
+            SS.explodeDistance = min(1e4, max(-1e4, SS.StringToMm(s)));
+            SS.MarkGroupDirty(SS.GW.activeGroup, true);
+            break;
+        }
         case Edit::DIGITS_AFTER_DECIMAL: {
             int v = atoi(s.c_str());
             if(v < 0 || v > 8) {
@@ -529,6 +497,11 @@ bool TextWindow::EditControlDoneForConfiguration(const std::string &s) {
             if(e) SS.gCode.depth = (float)SS.ExprToMm(e);
             break;
         }
+        case Edit::G_CODE_SAFE_HEIGHT: {
+            Expr *e = Expr::From(s, /*popUpError=*/true);
+            if(e) SS.gCode.safeHeight = (float)SS.ExprToMm(e);
+            break;
+        }
         case Edit::G_CODE_PASSES: {
             Expr *e = Expr::From(s, /*popUpError=*/true);
             if(e) SS.gCode.passes = (int)(e->Eval());
index 2acc21156f58ec33e952b489afbbacd9b6f1ccd0..6a25c26521ab15d6c0ce108d81e1ebb24eb7f2f1 100644 (file)
@@ -22,7 +22,11 @@ std::string Constraint::DescriptionString() const {
         case Type::EQ_LEN_PT_LINE_D:    s = C_("constr-name", "eq-length-and-pt-ln-dist"); break;
         case Type::EQ_PT_LN_DISTANCES:  s = C_("constr-name", "eq-pt-line-distances"); break;
         case Type::LENGTH_RATIO:        s = C_("constr-name", "length-ratio"); break;
+        case Type::ARC_ARC_LEN_RATIO:   s = C_("constr-name", "arc-arc-length-ratio"); break;
+        case Type::ARC_LINE_LEN_RATIO:  s = C_("constr-name", "arc-line-length-ratio"); break;
         case Type::LENGTH_DIFFERENCE:   s = C_("constr-name", "length-difference"); break;
+        case Type::ARC_ARC_DIFFERENCE:  s = C_("constr-name", "arc-arc-len-difference"); break;
+        case Type::ARC_LINE_DIFFERENCE: s = C_("constr-name", "arc-line-len-difference"); break;
         case Type::SYMMETRIC:           s = C_("constr-name", "symmetric"); break;
         case Type::SYMMETRIC_HORIZ:     s = C_("constr-name", "symmetric-h"); break;
         case Type::SYMMETRIC_VERT:      s = C_("constr-name", "symmetric-v"); break;
@@ -127,7 +131,7 @@ hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
         Entity::NO_ENTITY, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false);
 }
 
-void Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc) {
+bool Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc) {
     Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(),
            l1 = SK.GetEntity(line->point[1])->PointGetNum();
     Vector a1 = SK.GetEntity(arc->point[1])->PointGetNum(),
@@ -140,11 +144,12 @@ void Constraint::ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *ar
         Error(_("The tangent arc and line segment must share an "
                 "endpoint. Constrain them with Constrain -> "
                 "On Point before constraining tangent."));
-        return;
+        return false;
     }
+    return true;
 }
 
-void Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic) {
+bool Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic) {
     Vector l0 = SK.GetEntity(line->point[0])->PointGetNum(),
            l1 = SK.GetEntity(line->point[1])->PointGetNum();
     Vector as = cubic->CubicGetStartNum(),
@@ -158,11 +163,12 @@ void Constraint::ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *
         Error(_("The tangent cubic and line segment must share an "
                 "endpoint. Constrain them with Constrain -> "
                 "On Point before constraining tangent."));
-        return;
+        return false;
     }
+    return true;
 }
 
-void Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB) {
+bool Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB) {
     Vector as = eA->EndpointStart(),
            af = eA->EndpointFinish(),
            bs = eB->EndpointStart(),
@@ -183,8 +189,9 @@ void Constraint::ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *e
         Error(_("The curves must share an endpoint. Constrain them "
                 "with Constrain -> On Point before constraining "
                 "tangent."));
-        return;
+        return false;
     }
+    return true;
 }
 
 void Constraint::MenuConstrain(Command id) {
@@ -381,10 +388,27 @@ void Constraint::MenuConstrain(Command id) {
                 c.type = Type::LENGTH_RATIO;
                 c.entityA = gs.entity[0];
                 c.entityB = gs.entity[1];
+            }
+            else if(gs.arcs == 2 && gs.n == 2) {
+                c.type = Type::ARC_ARC_LEN_RATIO;
+                c.entityA = gs.entity[0];
+                c.entityB = gs.entity[1];
+            }
+            else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) {
+                c.type = Type::ARC_LINE_LEN_RATIO;
+                if(SK.GetEntity(gs.entity[0])->type == Entity::Type::ARC_OF_CIRCLE) {
+                    c.entityA = gs.entity[1];
+                    c.entityB = gs.entity[0];
+                } else {
+                    c.entityA = gs.entity[0];
+                    c.entityB = gs.entity[1];
+                }
             } else {
                 Error(_("Bad selection for length ratio constraint. This "
                         "constraint can apply to:\n\n"
-                        "    * two line segments\n"));
+                        "    * two line segments\n"
+                        "    * two arcs\n"
+                        "    * one arc and one line segment\n"));
                 return;
             }
 
@@ -398,10 +422,27 @@ void Constraint::MenuConstrain(Command id) {
                 c.type = Type::LENGTH_DIFFERENCE;
                 c.entityA = gs.entity[0];
                 c.entityB = gs.entity[1];
+            }
+            else if(gs.arcs == 2 && gs.n == 2) {
+                c.type = Type::ARC_ARC_DIFFERENCE;
+                c.entityA = gs.entity[0];
+                c.entityB = gs.entity[1];
+            }
+            else if(gs.lineSegments == 1 && gs.arcs == 1 && gs.n == 2) {
+                c.type = Type::ARC_LINE_DIFFERENCE;
+                if(SK.GetEntity(gs.entity[0])->type == Entity::Type::ARC_OF_CIRCLE) {
+                    c.entityA = gs.entity[1];
+                    c.entityB = gs.entity[0];
+                } else {
+                    c.entityA = gs.entity[0];
+                    c.entityB = gs.entity[1];
+                }
             } else {
                 Error(_("Bad selection for length difference constraint. This "
                         "constraint can apply to:\n\n"
-                        "    * two line segments\n"));
+                        "    * two line segments\n"
+                        "    * two arcs\n"
+                        "    * one arc and one line segment\n"));
                 return;
             }
 
@@ -417,8 +458,11 @@ void Constraint::MenuConstrain(Command id) {
                 c.ptA = gs.point[0];
 
                 // If a point is at-midpoint, then no reason to also constrain
-                // it on-line; so auto-remove that.
+                // it on-line; so auto-remove that.  Handle as one undo group.
+                SS.UndoRemember();
                 DeleteAllConstraintsFor(Type::PT_ON_LINE, c.entityA, c.ptA);
+                AddConstraint(&c, /*rememberForUndo=*/false);
+                break;
             } else if(gs.lineSegments == 1 && gs.workplanes == 1 && gs.n == 2) {
                 c.type = Type::AT_MIDPOINT;
                 int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0;
@@ -493,6 +537,7 @@ void Constraint::MenuConstrain(Command id) {
                             "(symmetric about workplane)\n"));
                 return;
             }
+            // We may remove constraints so remember manually
             if(c.entityA == Entity::NO_ENTITY) {
                 // Horizontal / vertical symmetry, implicit symmetry plane
                 // normal to the workplane
@@ -514,10 +559,14 @@ void Constraint::MenuConstrain(Command id) {
                 if(gs.lineSegments == 1) {
                     // If this line segment is already constrained horiz or
                     // vert, then auto-remove that redundant constraint.
+                    // Handle as one undo group.
+                    SS.UndoRemember();
                     DeleteAllConstraintsFor(Type::HORIZONTAL, (gs.entity[0]),
                         Entity::NO_ENTITY);
                     DeleteAllConstraintsFor(Type::VERTICAL, (gs.entity[0]),
                         Entity::NO_ENTITY);
+                    AddConstraint(&c, /*rememberForUndo=*/false);
+                    break;
                 }
             }
             AddConstraint(&c);
@@ -682,7 +731,9 @@ void Constraint::MenuConstrain(Command id) {
                 if(line->type == Entity::Type::ARC_OF_CIRCLE) {
                     swap(line, arc);
                 }
-                ConstrainArcLineTangent(&c, line, arc);
+                if(!ConstrainArcLineTangent(&c, line, arc)) {
+                    return;
+                }
                 c.type = Type::ARC_LINE_TANGENT;
                 c.entityA = arc->h;
                 c.entityB = line->h;
@@ -692,7 +743,9 @@ void Constraint::MenuConstrain(Command id) {
                 if(line->type == Entity::Type::CUBIC) {
                     swap(line, cubic);
                 }
-                ConstrainCubicLineTangent(&c, line, cubic);
+                if(!ConstrainCubicLineTangent(&c, line, cubic)) {
+                    return;
+                }
                 c.type = Type::CUBIC_LINE_TANGENT;
                 c.entityA = cubic->h;
                 c.entityB = line->h;
@@ -703,7 +756,9 @@ void Constraint::MenuConstrain(Command id) {
                 }
                 Entity *eA = SK.GetEntity(gs.entity[0]),
                        *eB = SK.GetEntity(gs.entity[1]);
-                ConstrainCurveCurveTangent(&c, eA, eB);
+                if(!ConstrainCurveCurveTangent(&c, eA, eB)) {
+                    return;
+                }
                 c.type = Type::CURVE_CURVE_TANGENT;
                 c.entityA = eA->h;
                 c.entityB = eB->h;
@@ -750,10 +805,19 @@ void Constraint::MenuConstrain(Command id) {
             break;
 
         case Command::COMMENT:
-            SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
-            SS.GW.pending.command = Command::COMMENT;
-            SS.GW.pending.description = _("click center of comment text");
-            SS.ScheduleShowTW();
+            if(gs.points == 1 && gs.n == 1) {
+                c.type = Type::COMMENT;
+                c.ptA = gs.point[0];
+                c.group       = SS.GW.activeGroup;
+                c.workplane   = SS.GW.ActiveWorkplane();
+                c.comment     = _("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
+                AddConstraint(&c);
+            } else {
+                SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND;
+                SS.GW.pending.command = Command::COMMENT;
+                SS.GW.pending.description = _("click center of comment text");
+                SS.ScheduleShowTW();
+            }
             break;
 
         default: ssassert(false, "Unexpected menu ID");
index 965a13d07519eb3ff35de2600405a6e1aa14a685..c21d1072179f8dd36aa6433b6f4043ea684350b9 100644 (file)
@@ -18,7 +18,11 @@ bool ConstraintBase::HasLabel() const {
         case Type::PROJ_PT_DISTANCE:
         case Type::DIAMETER:
         case Type::LENGTH_RATIO:
+        case Type::ARC_ARC_LEN_RATIO:  
+        case Type::ARC_LINE_LEN_RATIO: 
         case Type::LENGTH_DIFFERENCE:
+        case Type::ARC_ARC_DIFFERENCE: 
+        case Type::ARC_LINE_DIFFERENCE:
         case Type::ANGLE:
         case Type::COMMENT:
             return true;
@@ -39,7 +43,11 @@ bool ConstraintBase::IsProjectible() const {
         case Type::EQ_PT_LN_DISTANCES:
         case Type::EQUAL_ANGLE:
         case Type::LENGTH_RATIO:
+        case Type::ARC_ARC_LEN_RATIO:  
+        case Type::ARC_LINE_LEN_RATIO: 
         case Type::LENGTH_DIFFERENCE:
+        case Type::ARC_ARC_DIFFERENCE: 
+        case Type::ARC_LINE_DIFFERENCE:
         case Type::SYMMETRIC:
         case Type::SYMMETRIC_HORIZ:
         case Type::SYMMETRIC_VERT:
@@ -334,6 +342,110 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
             AddEq(l, (la->Div(lb))->Minus(exA), 0);
             return;
         }
+        
+        case Type::ARC_ARC_LEN_RATIO: {
+            EntityBase *arc1  = SK.GetEntity(entityA),
+                       *arc2  = SK.GetEntity(entityB);
+
+            // And get the arc1 radius, and the cosine of its angle
+            EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
+                       *as1 = SK.GetEntity(arc1->point[1]),
+                       *af1 = SK.GetEntity(arc1->point[2]);
+
+            ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
+                       aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
+            Expr *r1 = aof1.Magnitude();
+
+            ExprVector n1 = arc1->Normal()->NormalExprsN();
+            ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
+            ExprVector v1 = n1.Cross(u1);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta1 = aof1.Dot(u1)->Div(r1);
+            Expr *sintheta1 = aof1.Dot(v1)->Div(r1);
+
+            double thetas1, thetaf1, dtheta1;
+            arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
+            Expr *theta1;
+            if(dtheta1 < 3*PI/4) {
+                theta1 = costheta1->ACos();
+            } else if(dtheta1 < 5*PI/4) {
+                // As the angle crosses pi, cos theta1 is not invertible;
+                // so use the sine to stop blowing up
+                theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
+            } else {
+                theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
+            }
+            
+            // And get the arc2 radius, and the cosine of its angle
+            EntityBase *ao2 = SK.GetEntity(arc2->point[0]),
+                       *as2 = SK.GetEntity(arc2->point[1]),
+                       *af2 = SK.GetEntity(arc2->point[2]);
+
+            ExprVector aos2 = (as2->PointGetExprs()).Minus(ao2->PointGetExprs()),
+                       aof2 = (af2->PointGetExprs()).Minus(ao2->PointGetExprs());
+            Expr *r2 = aof2.Magnitude();
+
+            ExprVector n2 = arc2->Normal()->NormalExprsN();
+            ExprVector u2 = aos2.WithMagnitude(Expr::From(1.0));
+            ExprVector v2 = n2.Cross(u2);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta2 = aof2.Dot(u2)->Div(r2);
+            Expr *sintheta2 = aof2.Dot(v2)->Div(r2);
+
+            double thetas2, thetaf2, dtheta2;
+            arc2->ArcGetAngles(&thetas2, &thetaf2, &dtheta2);
+            Expr *theta2;
+            if(dtheta2 < 3*PI/4) {
+                theta2 = costheta2->ACos();
+            } else if(dtheta2 < 5*PI/4) {
+                // As the angle crosses pi, cos theta2 is not invertible;
+                // so use the sine to stop blowing up
+                theta2 = Expr::From(PI)->Minus(sintheta2->ASin());
+            } else {
+                theta2 = (Expr::From(2*PI))->Minus(costheta2->ACos());
+            }
+            // And write the equation; (r1*theta1) / ( r2*theta2) = some ratio
+            AddEq(l, (r1->Times(theta1))->Div(r2->Times(theta2))->Minus(exA), 0);
+            return;
+        }
+        
+        case Type::ARC_LINE_LEN_RATIO: {
+            EntityBase *line   = SK.GetEntity(entityA),
+                       *arc1   = SK.GetEntity(entityB);
+             
+            Expr *ll = Distance(workplane, line->point[0], line->point[1]);
+               
+            // And get the arc1 radius, and the cosine of its angle
+            EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
+                       *as1 = SK.GetEntity(arc1->point[1]),
+                       *af1 = SK.GetEntity(arc1->point[2]);
+
+            ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
+                       aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
+            Expr *r1 = aof1.Magnitude();
+            ExprVector n1 = arc1->Normal()->NormalExprsN();
+            ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
+            ExprVector v1 = n1.Cross(u1);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta1 = aof1.Dot(u1)->Div(r1);
+            Expr *sintheta1 = aof1.Dot(v1)->Div(r1);
+
+            double thetas1, thetaf1, dtheta1;
+            arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
+            Expr *theta1;
+            if(dtheta1 < 3*PI/4) {
+                theta1 = costheta1->ACos();
+            } else if(dtheta1 < 5*PI/4) {
+                // As the angle crosses pi, cos theta1 is not invertible;
+                // so use the sine to stop blowing up
+                theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
+            } else {
+                theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
+            }
+            // And write the equation; (r1*theta1) / ( length) = some ratio
+            AddEq(l, (r1->Times(theta1))->Div(ll)->Minus(exA), 0);
+            return;
+        }
 
         case Type::LENGTH_DIFFERENCE: {
             EntityBase *a = SK.GetEntity(entityA);
@@ -343,7 +455,111 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
             AddEq(l, (la->Minus(lb))->Minus(exA), 0);
             return;
         }
-
+        
+        case Type::ARC_ARC_DIFFERENCE: {
+            EntityBase *arc1  = SK.GetEntity(entityA),
+                       *arc2  = SK.GetEntity(entityB);
+
+            // And get the arc1 radius, and the cosine of its angle
+            EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
+                       *as1 = SK.GetEntity(arc1->point[1]),
+                       *af1 = SK.GetEntity(arc1->point[2]);
+
+            ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
+                       aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
+            Expr *r1 = aof1.Magnitude();
+
+            ExprVector n1 = arc1->Normal()->NormalExprsN();
+            ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
+            ExprVector v1 = n1.Cross(u1);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta1 = aof1.Dot(u1)->Div(r1);
+            Expr *sintheta1 = aof1.Dot(v1)->Div(r1);
+
+            double thetas1, thetaf1, dtheta1;
+            arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
+            Expr *theta1;
+            if(dtheta1 < 3*PI/4) {
+                theta1 = costheta1->ACos();
+            } else if(dtheta1 < 5*PI/4) {
+                // As the angle crosses pi, cos theta1 is not invertible;
+                // so use the sine to stop blowing up
+                theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
+            } else {
+                theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
+            }
+            
+            // And get the arc2 radius, and the cosine of its angle
+            EntityBase *ao2 = SK.GetEntity(arc2->point[0]),
+                       *as2 = SK.GetEntity(arc2->point[1]),
+                       *af2 = SK.GetEntity(arc2->point[2]);
+
+            ExprVector aos2 = (as2->PointGetExprs()).Minus(ao2->PointGetExprs()),
+                       aof2 = (af2->PointGetExprs()).Minus(ao2->PointGetExprs());
+            Expr *r2 = aof2.Magnitude();
+
+            ExprVector n2 = arc2->Normal()->NormalExprsN();
+            ExprVector u2 = aos2.WithMagnitude(Expr::From(1.0));
+            ExprVector v2 = n2.Cross(u2);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta2 = aof2.Dot(u2)->Div(r2);
+            Expr *sintheta2 = aof2.Dot(v2)->Div(r2);
+
+            double thetas2, thetaf2, dtheta2;
+            arc2->ArcGetAngles(&thetas2, &thetaf2, &dtheta2);
+            Expr *theta2;
+            if(dtheta2 < 3*PI/4) {
+                theta2 = costheta2->ACos();
+            } else if(dtheta2 < 5*PI/4) {
+                // As the angle crosses pi, cos theta2 is not invertible;
+                // so use the sine to stop blowing up
+                theta2 = Expr::From(PI)->Minus(sintheta2->ASin());
+            } else {
+                theta2 = (Expr::From(2*PI))->Minus(costheta2->ACos());
+            }
+            // And write the equation; (r1*theta1) - ( r2*theta2) = some difference
+            AddEq(l, (r1->Times(theta1))->Minus(r2->Times(theta2))->Minus(exA), 0);
+            return;
+        }
+        
+        case Type::ARC_LINE_DIFFERENCE: {
+            EntityBase *line   = SK.GetEntity(entityA),
+                       *arc1   = SK.GetEntity(entityB);
+             
+            Expr *ll = Distance(workplane, line->point[0], line->point[1]);
+               
+            // And get the arc1 radius, and the cosine of its angle
+            EntityBase *ao1 = SK.GetEntity(arc1->point[0]),
+                       *as1 = SK.GetEntity(arc1->point[1]),
+                       *af1 = SK.GetEntity(arc1->point[2]);
+
+            ExprVector aos1 = (as1->PointGetExprs()).Minus(ao1->PointGetExprs()),
+                       aof1 = (af1->PointGetExprs()).Minus(ao1->PointGetExprs());
+            Expr *r1 = aof1.Magnitude();
+            ExprVector n1 = arc1->Normal()->NormalExprsN();
+            ExprVector u1 = aos1.WithMagnitude(Expr::From(1.0));
+            ExprVector v1 = n1.Cross(u1);
+            // so in our new csys, we start at (1, 0, 0)
+            Expr *costheta1 = aof1.Dot(u1)->Div(r1);
+            Expr *sintheta1 = aof1.Dot(v1)->Div(r1);
+
+            double thetas1, thetaf1, dtheta1;
+            arc1->ArcGetAngles(&thetas1, &thetaf1, &dtheta1);
+            Expr *theta1;
+            if(dtheta1 < 3*PI/4) {
+                theta1 = costheta1->ACos();
+            } else if(dtheta1 < 5*PI/4) {
+                // As the angle crosses pi, cos theta1 is not invertible;
+                // so use the sine to stop blowing up
+                theta1 = Expr::From(PI)->Minus(sintheta1->ASin());
+            } else {
+                theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
+            }
+            // And write the equation; (r1*theta1) - ( length) = some difference
+            AddEq(l, (r1->Times(theta1))->Minus(ll)->Minus(exA), 0);
+            return;
+        }
+        
         case Type::DIAMETER: {
             EntityBase *circle = SK.GetEntity(entityA);
             Expr *r = circle->CircleGetRadiusExpr();
@@ -511,7 +727,7 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
                 }
             }
             return;
-
+        
         case Type::SYMMETRIC:
             if(workplane == EntityBase::FREE_IN_3D) {
                 EntityBase *plane = SK.GetEntity(entityA);
index 17f73612780cef259539967fb82a60345c070ac5..3e054a1ab4ad277d67f1606dc4daf4d616bb4653 100644 (file)
@@ -47,6 +47,7 @@ void TextWindow::ScreenConstraintToggleReference(int link, uint32_t v) {
     SS.UndoRemember();
     c->reference = !c->reference;
 
+    SS.MarkGroupDirty(c->group);
     SS.ScheduleShowTW();
 }
 
@@ -68,12 +69,19 @@ void TextWindow::DescribeSelection() {
         Entity *e = SK.GetEntity(gs.points == 1 ? gs.point[0] : gs.entity[0]);
         Vector p;
 
-#define COSTR(p) \
+#define COSTR_NO_LINK(p) \
     SS.MmToString((p).x).c_str(), \
     SS.MmToString((p).y).c_str(), \
     SS.MmToString((p).z).c_str()
-#define PT_AS_STR "(%Fi%s%E, %Fi%s%E, %Fi%s%E)"
-#define PT_AS_NUM "(%Fi%3%E, %Fi%3%E, %Fi%3%E)"
+#define PT_AS_STR_NO_LINK "(%Fi%s%Fd, %Fi%s%Fd, %Fi%s%Fd)"
+#define PT_AS_NUM "(%Fi%3%Fd, %Fi%3%Fd, %Fi%3%Fd)"
+#define COSTR(e, p) \
+    e->h, (&TextWindow::ScreenSelectEntity), (&TextWindow::ScreenHoverEntity), \
+        COSTR_NO_LINK(p)
+#define PT_AS_STR "%Ll%D%f%h" PT_AS_STR_NO_LINK "%E"
+#define CO_LINK(e, p) e->h, (&TextWindow::ScreenSelectEntity), (&TextWindow::ScreenHoverEntity), CO(p)
+#define PT_AS_NUM_LINK "%Ll%D%f%h" PT_AS_NUM "%E"
+
         switch(e->type) {
             case Entity::Type::POINT_IN_3D:
             case Entity::Type::POINT_IN_2D:
@@ -82,7 +90,7 @@ void TextWindow::DescribeSelection() {
             case Entity::Type::POINT_N_COPY:
             case Entity::Type::POINT_N_ROT_AA:
                 p = e->PointGetNum();
-                Printf(false, "%FtPOINT%E at " PT_AS_STR, COSTR(p));
+                Printf(false, "%FtPOINT%E at " PT_AS_STR, COSTR(e, p));
                 break;
 
             case Entity::Type::NORMAL_IN_3D:
@@ -103,20 +111,20 @@ void TextWindow::DescribeSelection() {
             case Entity::Type::WORKPLANE: {
                 p = SK.GetEntity(e->point[0])->PointGetNum();
                 Printf(false, "%FtWORKPLANE%E");
-                Printf(true, "   origin = " PT_AS_STR, COSTR(p));
+                Printf(true, "   origin = " PT_AS_STR, COSTR(SK.GetEntity(e->point[0]), p));
                 Quaternion q = e->Normal()->NormalGetNum();
                 p = q.RotationN();
-                Printf(true, "   normal = " PT_AS_NUM, CO(p));
+                Printf(true, "   normal = " PT_AS_NUM_LINK, CO_LINK(e->Normal(), p));
                 break;
             }
             case Entity::Type::LINE_SEGMENT: {
                 Vector p0 = SK.GetEntity(e->point[0])->PointGetNum();
                 p = p0;
                 Printf(false, "%FtLINE SEGMENT%E");
-                Printf(true,  "   thru " PT_AS_STR, COSTR(p));
+                Printf(true,  "   thru " PT_AS_STR, COSTR(SK.GetEntity(e->point[0]), p));
                 Vector p1 = SK.GetEntity(e->point[1])->PointGetNum();
                 p = p1;
-                Printf(false, "        " PT_AS_STR, COSTR(p));
+                Printf(false, "        " PT_AS_STR, COSTR(SK.GetEntity(e->point[1]), p));
                 Printf(true,  "   len = %Fi%s%E",
                     SS.MmToString((p1.Minus(p0).Magnitude())).c_str());
                 break;
@@ -136,18 +144,18 @@ void TextWindow::DescribeSelection() {
                 }
                 for(int i = 0; i < pts; i++) {
                     p = SK.GetEntity(e->point[i])->PointGetNum();
-                    Printf((i==0), "   p%d = " PT_AS_STR, i, COSTR(p));
+                    Printf((i==0), "   p%d = " PT_AS_STR, i, COSTR(SK.GetEntity(e->point[i]), p));
                 }
                 break;
 
             case Entity::Type::ARC_OF_CIRCLE: {
                 Printf(false, "%FtARC OF A CIRCLE%E");
                 p = SK.GetEntity(e->point[0])->PointGetNum();
-                Printf(true,  "     center = " PT_AS_STR, COSTR(p));
+                Printf(true,  "     center = " PT_AS_STR, COSTR(SK.GetEntity(e->point[0]), p));
                 p = SK.GetEntity(e->point[1])->PointGetNum();
-                Printf(true,  "  endpoints = " PT_AS_STR, COSTR(p));
+                Printf(true,  "  endpoints = " PT_AS_STR, COSTR(SK.GetEntity(e->point[1]), p));
                 p = SK.GetEntity(e->point[2])->PointGetNum();
-                Printf(false, "              " PT_AS_STR, COSTR(p));
+                Printf(false, "              " PT_AS_STR, COSTR(SK.GetEntity(e->point[2]), p));
                 double r = e->CircleGetRadiusNum();
                 Printf(true, "   diameter =  %Fi%s", SS.MmToString(r*2).c_str());
                 Printf(false, "     radius =  %Fi%s", SS.MmToString(r).c_str());
@@ -159,10 +167,11 @@ void TextWindow::DescribeSelection() {
             case Entity::Type::CIRCLE: {
                 Printf(false, "%FtCIRCLE%E");
                 p = SK.GetEntity(e->point[0])->PointGetNum();
-                Printf(true,  "     center = " PT_AS_STR, COSTR(p));
+                Printf(true,  "        center = " PT_AS_STR, COSTR(SK.GetEntity(e->point[0]), p));
                 double r = e->CircleGetRadiusNum();
-                Printf(true,  "   diameter =  %Fi%s", SS.MmToString(r*2).c_str());
-                Printf(false, "     radius =  %Fi%s", SS.MmToString(r).c_str());
+                Printf(true,  "      diameter =  %Fi%s", SS.MmToString(r*2).c_str());
+                Printf(false, "        radius =  %Fi%s", SS.MmToString(r).c_str());
+                Printf(false, " circumference =  %Fi%s", SS.MmToString(2*M_PI*r).c_str());
                 break;
             }
             case Entity::Type::FACE_NORMAL_PT:
@@ -174,7 +183,7 @@ void TextWindow::DescribeSelection() {
                 p = e->FaceGetNormalNum();
                 Printf(true,  "   normal = " PT_AS_NUM, CO(p));
                 p = e->FaceGetPointNum();
-                Printf(false, "     thru = " PT_AS_STR, COSTR(p));
+                Printf(false, "     thru = " PT_AS_STR, COSTR(e, p));
                 break;
 
             case Entity::Type::TTF_TEXT: {
@@ -314,11 +323,12 @@ void TextWindow::DescribeSelection() {
     } else if(gs.n == 2 && gs.points == 2) {
         Printf(false, "%FtTWO POINTS");
         Vector p0 = SK.GetEntity(gs.point[0])->PointGetNum();
-        Printf(true,  "   at " PT_AS_STR, COSTR(p0));
+        Printf(true,  "   at " PT_AS_STR, COSTR(SK.GetEntity(gs.point[0]), p0));
         Vector p1 = SK.GetEntity(gs.point[1])->PointGetNum();
-        Printf(false, "      " PT_AS_STR, COSTR(p1));
-        double d = (p1.Minus(p0)).Magnitude();
-        Printf(true, "  d = %Fi%s", SS.MmToString(d).c_str());
+        Printf(false, "      " PT_AS_STR, COSTR(SK.GetEntity(gs.point[1]), p1));
+        Vector dv = p1.Minus(p0);
+        Printf(true, "  d = %Fi%s", SS.MmToString(dv.Magnitude()).c_str());
+        Printf(false, "  d(x, y, z) = " PT_AS_STR_NO_LINK, COSTR_NO_LINK(dv));
     } else if(gs.n == 2 && gs.points == 1 && gs.circlesOrArcs == 1) {
         Entity *ec = SK.GetEntity(gs.entity[0]);
         if(ec->type == Entity::Type::CIRCLE) {
@@ -327,9 +337,9 @@ void TextWindow::DescribeSelection() {
             Printf(false, "%FtPOINT AND AN ARC");
         } else ssassert(false, "Unexpected entity type");
         Vector p = SK.GetEntity(gs.point[0])->PointGetNum();
-        Printf(true,  "        pt at " PT_AS_STR, COSTR(p));
+        Printf(true,  "        pt at " PT_AS_STR, COSTR(SK.GetEntity(gs.point[0]), p));
         Vector c = SK.GetEntity(ec->point[0])->PointGetNum();
-        Printf(true,  "     center = " PT_AS_STR, COSTR(c));
+        Printf(true,  "     center = " PT_AS_STR, COSTR(SK.GetEntity(ec->point[0]), c));
         double r = ec->CircleGetRadiusNum();
         Printf(false, "   diameter =  %Fi%s", SS.MmToString(r*2).c_str());
         Printf(false, "     radius =  %Fi%s", SS.MmToString(r).c_str());
@@ -338,22 +348,22 @@ void TextWindow::DescribeSelection() {
     } else if(gs.n == 2 && gs.faces == 1 && gs.points == 1) {
         Printf(false, "%FtA POINT AND A PLANE FACE");
         Vector pt = SK.GetEntity(gs.point[0])->PointGetNum();
-        Printf(true,  "        point = " PT_AS_STR, COSTR(pt));
+        Printf(true,  "        point = " PT_AS_STR, COSTR(SK.GetEntity(gs.point[0]), pt));
         Vector n = SK.GetEntity(gs.face[0])->FaceGetNormalNum();
         Printf(true,  " plane normal = " PT_AS_NUM, CO(n));
         Vector pl = SK.GetEntity(gs.face[0])->FaceGetPointNum();
-        Printf(false, "   plane thru = " PT_AS_STR, COSTR(pl));
+        Printf(false, "   plane thru = " PT_AS_STR, COSTR(SK.GetEntity(gs.face[0]), pl));
         double dd = n.Dot(pl) - n.Dot(pt);
         Printf(true,  "     distance = %Fi%s", SS.MmToString(dd).c_str());
     } else if(gs.n == 3 && gs.points == 2 && gs.vectors == 1) {
         Printf(false, "%FtTWO POINTS AND A VECTOR");
         Vector p0 = SK.GetEntity(gs.point[0])->PointGetNum();
-        Printf(true,  "  pointA = " PT_AS_STR, COSTR(p0));
+        Printf(true,  "  pointA = " PT_AS_STR, COSTR(SK.GetEntity(gs.point[0]), p0));
         Vector p1 = SK.GetEntity(gs.point[1])->PointGetNum();
-        Printf(false, "  pointB = " PT_AS_STR, COSTR(p1));
+        Printf(false, "  pointB = " PT_AS_STR, COSTR(SK.GetEntity(gs.point[1]), p1));
         Vector v  = SK.GetEntity(gs.vector[0])->VectorGetNum();
         v = v.WithMagnitude(1);
-        Printf(true,  "  vector = " PT_AS_NUM, CO(v));
+        Printf(true,  "  vector = " PT_AS_NUM_LINK, CO_LINK(SK.GetEntity(gs.vector[0]), v));
         double d = (p1.Minus(p0)).Dot(v);
         Printf(true,  "  proj_d = %Fi%s", SS.MmToString(d).c_str());
     } else if(gs.n == 2 && gs.lineSegments == 1 && gs.points == 1) {
@@ -361,11 +371,11 @@ void TextWindow::DescribeSelection() {
         Vector lp0 = SK.GetEntity(ln->point[0])->PointGetNum(),
                lp1 = SK.GetEntity(ln->point[1])->PointGetNum();
         Printf(false, "%FtLINE SEGMENT AND POINT%E");
-        Printf(true,  "   ln thru " PT_AS_STR, COSTR(lp0));
-        Printf(false, "           " PT_AS_STR, COSTR(lp1));
+        Printf(true,  "   ln thru " PT_AS_STR, COSTR(SK.GetEntity(ln->point[0]), lp0));
+        Printf(false, "           " PT_AS_STR, COSTR(SK.GetEntity(ln->point[1]), lp1));
         Entity *p  = SK.GetEntity(gs.point[0]);
         Vector pp = p->PointGetNum();
-        Printf(true,  "     point " PT_AS_STR, COSTR(pp));
+        Printf(true,  "     point " PT_AS_STR, COSTR(p, pp));
         Printf(true,  " pt-ln distance = %Fi%s%E",
             SS.MmToString(pp.DistanceToLine(lp0, lp1.Minus(lp0))).c_str());
         hEntity wrkpl = SS.GW.ActiveWorkplane();
@@ -384,8 +394,8 @@ void TextWindow::DescribeSelection() {
         v0 = v0.WithMagnitude(1);
         v1 = v1.WithMagnitude(1);
 
-        Printf(true,  "  vectorA = " PT_AS_NUM, CO(v0));
-        Printf(false, "  vectorB = " PT_AS_NUM, CO(v1));
+        Printf(true,  "  vectorA = " PT_AS_NUM_LINK, CO_LINK(SK.GetEntity(gs.entity[0]), v0));
+        Printf(false, "  vectorB = " PT_AS_NUM_LINK, CO_LINK(SK.GetEntity(gs.entity[1]), v1));
 
         double theta = acos(v0.Dot(v1));
         Printf(true,  "    angle = %Fi%2%E degrees", theta*180/PI);
@@ -398,12 +408,12 @@ void TextWindow::DescribeSelection() {
         Vector n0 = SK.GetEntity(gs.face[0])->FaceGetNormalNum();
         Printf(true,  " planeA normal = " PT_AS_NUM, CO(n0));
         Vector p0 = SK.GetEntity(gs.face[0])->FaceGetPointNum();
-        Printf(false, "   planeA thru = " PT_AS_STR, COSTR(p0));
+        Printf(false, "   planeA thru = " PT_AS_STR, COSTR(SK.GetEntity(gs.face[0]), p0));
 
         Vector n1 = SK.GetEntity(gs.face[1])->FaceGetNormalNum();
         Printf(true,  " planeB normal = " PT_AS_NUM, CO(n1));
         Vector p1 = SK.GetEntity(gs.face[1])->FaceGetPointNum();
-        Printf(false, "   planeB thru = " PT_AS_STR, COSTR(p1));
+        Printf(false, "   planeB thru = " PT_AS_STR, COSTR(SK.GetEntity(gs.face[1]), p1));
 
         double theta = acos(n0.Dot(n1));
         Printf(true,  "         angle = %Fi%2%E degrees", theta*180/PI);
index ccaeb961d4302bd748cf8e43f53400328492ad40..3610f20180b20cad59d246a667ba9256a2bc6579 100644 (file)
@@ -210,16 +210,15 @@ void GraphicsWindow::SelectByMarquee() {
     BBox marqueeBBox = BBox::From(Vector::From(marqueePoint.x, marqueePoint.y, VERY_NEGATIVE),
                                   Vector::From(orig.mouse.x,   orig.mouse.y,   VERY_POSITIVE));
 
-    Entity *e;
-    for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-        if(e->group != SS.GW.activeGroup) continue;
-        if(e->IsFace() || e->IsDistance()) continue;
-        if(!e->IsVisible()) continue;
+    for(Entity &e : SK.entity) {
+        if(e.group != SS.GW.activeGroup) continue;
+        if(e.IsFace() || e.IsDistance()) continue;
+        if(!e.IsVisible()) continue;
 
         bool entityHasBBox;
-        BBox entityBBox = e->GetOrGenerateScreenBBox(&entityHasBBox);
+        BBox entityBBox = e.GetOrGenerateScreenBBox(&entityHasBBox);
         if(entityHasBBox && entityBBox.Overlaps(marqueeBBox)) {
-            MakeSelected(e->h);
+            MakeSelected(e.h);
         }
     }
 }
@@ -412,8 +411,8 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
         cached.projRight = projRight;
         cached.projUp = projUp;
         cached.scale = scale;
-        for(Entity *e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-            e->screenBBoxValid = false;
+        for(Entity &e : SK.entity) {
+            e.screenBBoxValid = false;
         }
     }
 
index 2cdb9afce56b68c310298cde4575e439f5a52c3c..02aababbc266bd4cd2d352acd3f751301bb11552 100644 (file)
@@ -12,7 +12,7 @@ std::string Constraint::Label() const {
     std::string result;
     if(type == Type::ANGLE) {
         result = SS.DegreeToString(valA) + "°";
-    } else if(type == Type::LENGTH_RATIO) {
+    } else if(type == Type::LENGTH_RATIO || type == Type::ARC_ARC_LEN_RATIO || type == Type::ARC_LINE_LEN_RATIO) {
         result = ssprintf("%.3f:1", valA);
     } else if(type == Type::COMMENT) {
         result = comment;
@@ -267,7 +267,7 @@ void Constraint::DoEqualRadiusTicks(Canvas *canvas, Canvas::hStroke hcs,
     const Camera &camera = canvas->GetCamera();
     Entity *circ = SK.GetEntity(he);
 
-    Vector center = SK.GetEntity(circ->point[0])->PointGetNum();
+    Vector center = SK.GetEntity(circ->point[0])->PointGetDrawNum();
     double r = circ->CircleGetRadiusNum();
     Quaternion q = circ->Normal()->NormalGetNum();
     Vector u = q.RotationU(), v = q.RotationV();
@@ -291,7 +291,8 @@ void Constraint::DoEqualRadiusTicks(Canvas *canvas, Canvas::hStroke hcs,
 
 void Constraint::DoArcForAngle(Canvas *canvas, Canvas::hStroke hcs,
                                Vector a0, Vector da, Vector b0, Vector db,
-                               Vector offset, Vector *ref, bool trim)
+                               Vector offset, Vector *ref, bool trim,
+                               Vector explodeOffset)
 {
     const Camera &camera = canvas->GetCamera();
     double pixels = 1.0 / camera.scale;
@@ -305,6 +306,9 @@ void Constraint::DoArcForAngle(Canvas *canvas, Canvas::hStroke hcs,
         db = db.ProjectVectorInto(workplane);
     }
 
+    a0 = a0.Plus(explodeOffset);
+    b0 = b0.Plus(explodeOffset);
+
     Vector a1 = a0.Plus(da);
     Vector b1 = b0.Plus(db);
 
@@ -534,6 +538,15 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 DoProjectedPoint(canvas, hcs, &bp);
             }
 
+            if(ShouldDrawExploded()) {
+                // Offset A and B by the same offset so the constraint is drawn
+                // in the plane of one of the exploded points (rather than at an
+                // angle)
+                Vector offset = SK.GetEntity(ptA)->ExplodeOffset();
+                ap = ap.Plus(offset);
+                bp = bp.Plus(offset);
+            }
+
             Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);
             if(refs) refs->push_back(ref);
 
@@ -548,6 +561,19 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                    dp = (bp.Minus(ap)),
                    pp = SK.GetEntity(entityA)->VectorGetNum();
 
+            if(ShouldDrawExploded()) {
+                // explode for whichever point is in the workplane (or the first if both are) 
+                Entity *pt = SK.GetEntity(ptA);
+                if(pt->group != group) {
+                    pt = SK.GetEntity(ptB);
+                }
+                if(pt->group == group) {
+                    Vector offset = pt->ExplodeOffset();
+                    ap = ap.Plus(offset);
+                    bp = bp.Plus(offset);
+                }
+            }
+
             Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);
             if(refs) refs->push_back(ref);
 
@@ -564,7 +590,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
 
         case Type::PT_FACE_DISTANCE:
         case Type::PT_PLANE_DISTANCE: {
-            Vector pt = SK.GetEntity(ptA)->PointGetNum();
+            Vector pt = SK.GetEntity(ptA)->PointGetDrawNum();
             Entity *enta = SK.GetEntity(entityA);
             Vector n, p;
             if(type == Type::PT_PLANE_DISTANCE) {
@@ -590,7 +616,8 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
         }
 
         case Type::PT_LINE_DISTANCE: {
-            Vector pt = SK.GetEntity(ptA)->PointGetNum();
+            Entity *ptEntity = SK.GetEntity(ptA);
+            Vector pt = ptEntity->PointGetNum();
             Entity *line = SK.GetEntity(entityA);
             Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
             Vector lB = SK.GetEntity(line->point[1])->PointGetNum();
@@ -602,6 +629,19 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 DoProjectedPoint(canvas, hcs, &pt);
             }
 
+            // Only explode if the point and line are in the same group (and that group is a sketch
+            // with explode enabled) otherwise it's too visually confusing to figure out what the
+            // correct projections should be.
+            bool shouldExplode = ShouldDrawExploded()
+                && ptEntity->group == group
+                && line->group == group;
+            if(shouldExplode) {
+                Vector explodeOffset = ptEntity->ExplodeOffset();
+                pt = pt.Plus(explodeOffset);
+                lA = lA.Plus(explodeOffset);
+                lB = lB.Plus(explodeOffset);
+            }
+
             // Find the closest point on the line
             Vector closest = pt.ClosestPointOnLine(lA, dl);
 
@@ -655,7 +695,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
 
         case Type::DIAMETER: {
             Entity *circle = SK.GetEntity(entityA);
-            Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
+            Vector center = SK.GetEntity(circle->point[0])->PointGetDrawNum();
             Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum();
             Vector n = q.RotationN().WithMagnitude(1);
             double r = circle->CircleGetRadiusNum();
@@ -697,7 +737,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 Vector r = camera.projRight.ScaledBy((a+1)/camera.scale);
                 Vector d = camera.projUp.ScaledBy((2-a)/camera.scale);
                 for(int i = 0; i < 2; i++) {
-                    Vector p = SK.GetEntity(i == 0 ? ptA : ptB)-> PointGetNum();
+                    Vector p = SK.GetEntity(i == 0 ? ptA : ptB)->PointGetDrawNum();
                     if(refs) refs->push_back(p);
                     canvas->DrawQuad(p.Plus (r).Plus (d),
                                      p.Plus (r).Minus(d),
@@ -715,7 +755,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
         case Type::PT_ON_FACE:
         case Type::PT_IN_PLANE: {
             double s = 8/camera.scale;
-            Vector p = SK.GetEntity(ptA)->PointGetNum();
+            Vector p = SK.GetEntity(ptA)->PointGetDrawNum();
             if(refs) refs->push_back(p);
             Vector r, d;
             if(type == Type::PT_ON_FACE) {
@@ -740,7 +780,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
         }
 
         case Type::WHERE_DRAGGED: {
-            Vector p = SK.GetEntity(ptA)->PointGetNum();
+            Vector p = SK.GetEntity(ptA)->PointGetDrawNum();
             if(refs) refs->push_back(p);
             Vector u = p.Plus(gu.WithMagnitude(8/camera.scale)).Plus(
                               gr.WithMagnitude(8/camera.scale)),
@@ -797,10 +837,10 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             }
 
             DoArcForAngle(canvas, hcs, a0, da, b0, db,
-                da.WithMagnitude(40/camera.scale), &ref, /*trim=*/false);
+                da.WithMagnitude(40/camera.scale), &ref, /*trim=*/false, a->ExplodeOffset());
             if(refs) refs->push_back(ref);
             DoArcForAngle(canvas, hcs, c0, dc, d0, dd,
-                dc.WithMagnitude(40/camera.scale), &ref, /*trim=*/false);
+                dc.WithMagnitude(40/camera.scale), &ref, /*trim=*/false, c->ExplodeOffset());
             if(refs) refs->push_back(ref);
 
             return;
@@ -820,7 +860,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             }
 
             Vector ref;
-            DoArcForAngle(canvas, hcs, a0, da, b0, db, disp.offset, &ref, /*trim=*/true);
+            DoArcForAngle(canvas, hcs, a0, da, b0, db, disp.offset, &ref, /*trim=*/true, a->ExplodeOffset());
             DoLabel(canvas, hcs, ref, labelPos, gr, gu);
             if(refs) refs->push_back(ref);
             return;
@@ -855,7 +895,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                     if(u.Dot(ru) < 0) u = u.ScaledBy(-1);
                 }
 
-                Vector p = e->VectorGetRefPoint();
+                Vector p = e->VectorGetRefPoint().Plus(e->ExplodeOffset());
                 Vector s = p.Plus(u).Plus(v);
                 DoLine(canvas, hcs, s, s.Plus(v));
                 Vector m = s.Plus(v.ScaledBy(0.5));
@@ -873,9 +913,9 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             if(type == Type::ARC_LINE_TANGENT) {
                 Entity *arc = SK.GetEntity(entityA);
                 Entity *norm = SK.GetEntity(arc->normal);
-                Vector c = SK.GetEntity(arc->point[0])->PointGetNum();
+                Vector c = SK.GetEntity(arc->point[0])->PointGetDrawNum();
                 Vector p =
-                    SK.GetEntity(arc->point[other ? 2 : 1])->PointGetNum();
+                    SK.GetEntity(arc->point[other ? 2 : 1])->PointGetDrawNum();
                 Vector r = p.Minus(c);
                 textAt = p.Plus(r.WithMagnitude(14/camera.scale));
                 u = norm->NormalU();
@@ -896,6 +936,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 Entity *cubic = SK.GetEntity(entityA);
                 Vector p = other ? cubic->CubicGetFinishNum() :
                                    cubic->CubicGetStartNum();
+                p = p.Plus(cubic->ExplodeOffset());
                 Vector dir = SK.GetEntity(entityB)->VectorGetNum();
                 Vector out = n.Cross(dir);
                 textAt = p.Plus(out.WithMagnitude(14/camera.scale));
@@ -905,12 +946,12 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 u = wn->NormalU();
                 v = wn->NormalV();
                 n = wn->NormalN();
-                EntityBase *eA = SK.GetEntity(entityA);
+                Entity *eA = SK.GetEntity(entityA);
                 // Big pain; we have to get a vector tangent to the curve
                 // at the shared point, which could be from either a cubic
                 // or an arc.
                 if(other) {
-                    textAt = eA->EndpointFinish();
+                    textAt = eA->EndpointFinish().Plus(eA->ExplodeOffset());
                     if(eA->type == Entity::Type::CUBIC) {
                         dir = eA->CubicGetFinishTangentNum();
                     } else {
@@ -919,7 +960,7 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                         dir = n.Cross(dir);
                     }
                 } else {
-                    textAt = eA->EndpointStart();
+                    textAt = eA->EndpointStart().Plus(eA->ExplodeOffset());
                     if(eA->type == Entity::Type::CUBIC) {
                         dir = eA->CubicGetStartTangentNum();
                     } else {
@@ -947,6 +988,10 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 Vector u = (gn.Cross(n)).WithMagnitude(4/camera.scale);
                 Vector p = e->VectorGetRefPoint();
 
+                if(ShouldDrawExploded()) {
+                    p = p.Plus(e->ExplodeOffset());
+                }
+
                 DoLine(canvas, hcs, p.Plus(u), p.Plus(u).Plus(n));
                 DoLine(canvas, hcs, p.Minus(u), p.Minus(u).Plus(n));
                 if(refs) refs->push_back(p.Plus(n.ScaledBy(0.5)));
@@ -967,8 +1012,8 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             Entity *line = SK.GetEntity(entityA);
             Vector ref;
             DoEqualLenTicks(canvas, hcs,
-                SK.GetEntity(line->point[0])->PointGetNum(),
-                SK.GetEntity(line->point[1])->PointGetNum(),
+                SK.GetEntity(line->point[0])->PointGetDrawNum(),
+                SK.GetEntity(line->point[1])->PointGetDrawNum(),
                 gn, &ref);
             if(refs) refs->push_back(ref);
             DoEqualRadiusTicks(canvas, hcs, entityB, &ref);
@@ -990,6 +1035,12 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                     DoProjectedPoint(canvas, hcs, &b);
                 }
 
+                if(ShouldDrawExploded()) {
+                    Vector offset = e->ExplodeOffset();
+                    a = a.Plus(offset);
+                    b = b.Plus(offset);
+                }
+
                 Vector ref;
                 DoEqualLenTicks(canvas, hcs, a, b, gn, &ref);
                 if(refs) refs->push_back(ref);
@@ -1000,7 +1051,42 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             }
             return;
         }
+        case Type::ARC_ARC_LEN_RATIO:
+        case Type::ARC_ARC_DIFFERENCE: {
+            Entity *circle = SK.GetEntity(entityA);
+            Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
+            Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum();
+            Vector n = q.RotationN().WithMagnitude(1);
 
+            Vector ref2;
+            DoEqualRadiusTicks(canvas, hcs, entityA, &ref2);
+            DoEqualRadiusTicks(canvas, hcs, entityB, &ref2);
+            
+            Vector ref = center.Plus(disp.offset);
+            // Force the label into the same plane as the circle.
+            ref = ref.Minus(n.ScaledBy(n.Dot(ref) - n.Dot(center)));
+            if(refs) refs->push_back(ref);
+            Vector topLeft;
+            DoLabel(canvas, hcs, ref, &topLeft, gr, gu);
+            if(labelPos) *labelPos = topLeft;
+            return;
+        }
+        case Type::ARC_LINE_LEN_RATIO:
+        case Type::ARC_LINE_DIFFERENCE: {
+            Vector a, b = Vector::From(0, 0, 0);
+            Vector ref;
+            Entity *e = SK.GetEntity(entityA);
+            a = SK.GetEntity(e->point[0])->PointGetNum();
+            b = SK.GetEntity(e->point[1])->PointGetNum();
+            DoEqualLenTicks(canvas, hcs, a, b, gn, &ref);
+            if(refs) refs->push_back(ref);
+            DoEqualRadiusTicks(canvas, hcs, entityB, &ref);
+            if(refs) refs->push_back(ref);
+            ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset);
+            DoLabel(canvas, hcs, ref, labelPos, gr, gu);
+            return;
+        }
+        
         case Type::EQ_LEN_PT_LINE_D: {
             Entity *forLen = SK.GetEntity(entityA);
             Vector a = SK.GetEntity(forLen->point[0])->PointGetNum(),
@@ -1009,6 +1095,11 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 DoProjectedPoint(canvas, hcs, &a);
                 DoProjectedPoint(canvas, hcs, &b);
             }
+            if(ShouldDrawExploded()) {
+                Vector offset = forLen->ExplodeOffset();
+                a = a.Plus(offset);
+                b = b.Plus(offset);
+            }
             Vector refa;
             DoEqualLenTicks(canvas, hcs, a, b, gn, &refa);
             if(refs) refs->push_back(refa);
@@ -1024,6 +1115,11 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             }
 
             Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la));
+            if(ShouldDrawExploded()) {
+                Vector offset = SK.GetEntity(ptA)->ExplodeOffset();
+                pt = pt.Plus(offset);
+                closest = closest.Plus(offset);
+            }
             DoLine(canvas, hcs, pt, closest);
             Vector refb;
             DoEqualLenTicks(canvas, hcs, pt, closest, gn, &refb);
@@ -1046,6 +1142,11 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
                 }
 
                 Vector closest = pt.ClosestPointOnLine(la, lb.Minus(la));
+                if(ShouldDrawExploded()) {
+                    Vector offset = pte->ExplodeOffset();
+                    pt = pt.Plus(offset);
+                    closest = closest.Plus(offset);
+                }
                 DoLine(canvas, hcs, pt, closest);
 
                 Vector ref;
@@ -1075,8 +1176,8 @@ void Constraint::DoLayout(DrawAs how, Canvas *canvas,
             goto s;
         }
 s:
-            Vector a = SK.GetEntity(ptA)->PointGetNum();
-            Vector b = SK.GetEntity(ptB)->PointGetNum();
+            Vector a = SK.GetEntity(ptA)->PointGetDrawNum();
+            Vector b = SK.GetEntity(ptB)->PointGetDrawNum();
 
             for(int i = 0; i < 2; i++) {
                 Vector tail = (i == 0) ? a : b;
@@ -1113,8 +1214,8 @@ s:
                 }
                 // For "at midpoint", this branch is always taken.
                 Entity *e = SK.GetEntity(entityA);
-                Vector a = SK.GetEntity(e->point[0])->PointGetNum();
-                Vector b = SK.GetEntity(e->point[1])->PointGetNum();
+                Vector a = SK.GetEntity(e->point[0])->PointGetDrawNum();
+                Vector b = SK.GetEntity(e->point[1])->PointGetDrawNum();
                 Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5));
                 Vector offset = (a.Minus(b)).Cross(n);
                 offset = offset.WithMagnitude(textHeight);
@@ -1138,8 +1239,8 @@ s:
                                        r.WithMagnitude(1), u.WithMagnitude(1), hcs);
                 if(refs) refs->push_back(o);
             } else {
-                Vector a = SK.GetEntity(ptA)->PointGetNum();
-                Vector b = SK.GetEntity(ptB)->PointGetNum();
+                Vector a = SK.GetEntity(ptA)->PointGetDrawNum();
+                Vector b = SK.GetEntity(ptB)->PointGetDrawNum();
 
                 Entity *w = SK.GetEntity(workplane);
                 Vector cu = w->Normal()->NormalU();
@@ -1189,8 +1290,13 @@ s:
                 }
                 hcs = canvas->GetStroke(stroke);
             }
-            DoLabel(canvas, hcs, disp.offset, labelPos, u, v);
-            if(refs) refs->push_back(disp.offset);
+            Vector ref = disp.offset;
+            if(ptA.v) {
+                Vector a = SK.GetEntity(ptA)->PointGetNum();
+                ref = a.Plus(disp.offset);
+            }
+            DoLabel(canvas, hcs, ref, labelPos, u, v);
+            if(refs) refs->push_back(ref);
             return;
         }
     }
@@ -1238,7 +1344,11 @@ bool Constraint::HasLabel() const {
         case Type::PT_FACE_DISTANCE:
         case Type::PROJ_PT_DISTANCE:
         case Type::LENGTH_RATIO:
+        case Type::ARC_ARC_LEN_RATIO:
+        case Type::ARC_LINE_LEN_RATIO:
         case Type::LENGTH_DIFFERENCE:
+        case Type::ARC_ARC_DIFFERENCE:
+        case Type::ARC_LINE_DIFFERENCE:
         case Type::DIAMETER:
         case Type::ANGLE:
             return true;
@@ -1247,3 +1357,7 @@ bool Constraint::HasLabel() const {
             return false;
     }
 }
+
+bool Constraint::ShouldDrawExploded() const {
+    return SK.GetGroup(group)->ShouldDrawExploded();
+}
index b8e3cbd5edbd33102c3df085f8d35b4b2c0ab0d4..d00925449cd59663fef2cd2d6982753e74348b13 100644 (file)
@@ -26,7 +26,7 @@ void Entity::GenerateEdges(SEdgeList *el) {
         List<Vector> lv = {};
         sb->MakePwlInto(&lv);
         for(int j = 1; j < lv.n; j++) {
-            el->AddEdge(lv[j-1], lv[j], style.v, i);
+            el->AddEdge(lv[j-1], lv[j], Style::ForEntity(h).v, i);
         }
         lv.Clear();
     }
@@ -88,7 +88,7 @@ void Entity::GetReferencePoints(std::vector<Vector> *refs) {
         case Type::POINT_N_ROT_AXIS_TRANS:
         case Type::POINT_IN_3D:
         case Type::POINT_IN_2D:
-            refs->push_back(PointGetNum());
+            refs->push_back(PointGetDrawNum());
             break;
 
         case Type::NORMAL_N_COPY:
@@ -103,12 +103,12 @@ void Entity::GetReferencePoints(std::vector<Vector> *refs) {
         case Type::CUBIC_PERIODIC:
         case Type::TTF_TEXT:
         case Type::IMAGE:
-            refs->push_back(SK.GetEntity(point[0])->PointGetNum());
+            refs->push_back(SK.GetEntity(point[0])->PointGetDrawNum());
             break;
 
         case Type::LINE_SEGMENT: {
-            Vector a = SK.GetEntity(point[0])->PointGetNum(),
-                   b = SK.GetEntity(point[1])->PointGetNum();
+            Vector a = SK.GetEntity(point[0])->PointGetDrawNum(),
+                   b = SK.GetEntity(point[1])->PointGetDrawNum();
             refs->push_back(b.Plus(a.Minus(b).ScaledBy(0.5)));
             break;
         }
@@ -462,10 +462,30 @@ void Entity::GenerateBezierCurves(SBezierList *sbl) const {
 
     // Record our style for all of the Beziers that we just created.
     for(; i < sbl->l.n; i++) {
-        sbl->l[i].auxA = style.v;
+        sbl->l[i].auxA = Style::ForEntity(h).v;
     }
 }
 
+bool Entity::ShouldDrawExploded() const {
+    return SK.GetGroup(group)->ShouldDrawExploded();
+}
+
+Vector Entity::ExplodeOffset() const {
+    if(ShouldDrawExploded() && workplane.v != 0) {
+        int requestIdx = SK.GetRequest(h.request())->groupRequestIndex;
+        double offset = SS.explodeDistance * (requestIdx + 1);
+        return SK.GetEntity(workplane)->Normal()->NormalN().ScaledBy(offset);
+    } else {
+        return Vector::From(0, 0, 0);
+    }
+}
+
+Vector Entity::PointGetDrawNum() const {
+    // As per EntityBase::PointGetNum but specifically for when drawing/rendering the point
+    // (and not when solving), so we can potentially draw it somewhere different
+    return PointGetNum().Plus(ExplodeOffset());
+}
+
 void Entity::Draw(DrawAs how, Canvas *canvas) {
     if(!(how == DrawAs::HOVERED || how == DrawAs::SELECTED) &&
        !IsVisible()) return;
@@ -557,16 +577,17 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
             pointStroke.unit   = Canvas::Unit::PX;
             Canvas::hStroke hcsPoint = canvas->GetStroke(pointStroke);
 
+            Vector p = PointGetDrawNum();
             if(free) {
                 Canvas::Stroke analyzeStroke = Style::Stroke(Style::ANALYZE);
                 analyzeStroke.width = 14.0;
                 analyzeStroke.layer = Canvas::Layer::FRONT;
                 Canvas::hStroke hcsAnalyze = canvas->GetStroke(analyzeStroke);
 
-                canvas->DrawPoint(PointGetNum(), hcsAnalyze);
+                canvas->DrawPoint(p, hcsAnalyze);
             }
 
-            canvas->DrawPoint(PointGetNum(), hcsPoint);
+            canvas->DrawPoint(p, hcsPoint);
             return;
         }
 
@@ -621,7 +642,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
                     tail = camera.projRight.ScaledBy(w/s).Plus(
                            camera.projUp.   ScaledBy(h/s)).Minus(camera.offset);
                 } else {
-                    tail = SK.GetEntity(point[0])->PointGetNum();
+                    tail = SK.GetEntity(point[0])->PointGetDrawNum();
                 }
                 tail = camera.AlignToPixelGrid(tail);
 
@@ -709,8 +730,32 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
         case Type::TTF_TEXT: {
             // Generate the rational polynomial curves, then piecewise linearize
             // them, and display those.
-            if(!canvas->DrawBeziers(*GetOrGenerateBezierCurves(),  hcs)) {
-                canvas->DrawEdges(*GetOrGenerateEdges(), hcs);
+            // Calculating the draw offset, if necessary.
+            const bool shouldExplode = ShouldDrawExploded();
+            Vector explodeOffset;
+            SBezierList offsetBeziers = {};
+            SBezierList *beziers = GetOrGenerateBezierCurves();
+            if(shouldExplode) {
+                explodeOffset = ExplodeOffset();
+                for(const SBezier& b : beziers->l) {
+                    SBezier offset = b.TransformedBy(explodeOffset, Quaternion::IDENTITY, 1.0);
+                    offsetBeziers.l.Add(&offset);
+                }
+                beziers = &offsetBeziers;
+            }
+
+            SEdgeList *edges = nullptr;
+            SEdgeList offsetEdges = {};
+
+            if(!canvas->DrawBeziers(*beziers, hcs)) {
+                edges = GetOrGenerateEdges();
+                if(shouldExplode) {
+                    for(const SEdge &e : edges->l) {
+                        offsetEdges.AddEdge(e.a.Plus(explodeOffset), e.b.Plus(explodeOffset), e.auxA, e.auxB, e.tag);
+                    }
+                    edges = &offsetEdges;
+                }
+                canvas->DrawEdges(*edges, hcs);
             }
             if(type == Type::CIRCLE) {
                 Entity *dist = SK.GetEntity(distance);
@@ -720,12 +765,14 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
                         Canvas::Stroke analyzeStroke = Style::Stroke(Style::ANALYZE);
                         analyzeStroke.layer = Canvas::Layer::FRONT;
                         Canvas::hStroke hcsAnalyze = canvas->GetStroke(analyzeStroke);
-                        if(!canvas->DrawBeziers(*GetOrGenerateBezierCurves(), hcsAnalyze)) {
-                            canvas->DrawEdges(*GetOrGenerateEdges(), hcsAnalyze);
+                        if(!canvas->DrawBeziers(*beziers, hcsAnalyze)) {
+                            canvas->DrawEdges(*edges, hcsAnalyze);
                         }
                     }
                 }
             }
+            offsetBeziers.Clear();
+            offsetEdges.Clear();
             return;
         }
         case Type::IMAGE: {
@@ -757,7 +804,7 @@ void Entity::Draw(DrawAs how, Canvas *canvas) {
             Canvas::hFill hf = canvas->GetFill(fill);
             Vector v[4] = {};
             for(int i = 0; i < 4; i++) {
-                v[i] = SK.GetEntity(point[i])->PointGetNum();
+                v[i] = SK.GetEntity(point[i])->PointGetDrawNum();
             }
             Vector iu = v[3].Minus(v[0]);
             Vector iv = v[1].Minus(v[0]);
index 93403bca01b220e5b8ff814c7cba03a8de59d9a7..19f08686bc36c998f1c66f94d9ed4d4d3200f84b 100644 (file)
--- a/src/dsc.h
+++ b/src/dsc.h
@@ -10,6 +10,7 @@
 #include "solvespace.h"
 
 #include <type_traits>
+#include <vector>
 
 /// Trait indicating which types are handle types and should get the associated operators.
 /// Specialize for each handle type and inherit from std::true_type.
@@ -371,15 +372,28 @@ public:
     }
 };
 
+template<class T, class H> class IdList;
+
 // Comparison functor used by IdList and related classes
 template <class T, class H>
 struct CompareId {
-    bool operator()(T const& lhs, T const& rhs) const {
-        return lhs.h.v < rhs.h.v;
+
+    CompareId(const IdList<T, H> *list) {
+        idlist = list;
+    }
+
+    bool operator()(int lhs, T const& rhs) const {
+        return idlist->elemstore[lhs].h.v < rhs.h.v;
+    }
+    bool operator()(int lhs, H rhs) const {
+        return idlist->elemstore[lhs].h.v < rhs.v;
     }
-    bool operator()(T const& lhs, H rhs) const {
-        return lhs.h.v < rhs.v;
+    bool operator()(T *lhs, int rhs) const {
+        return lhs->h.v < idlist->elemstore[rhs].h.v;
     }
+
+private:
+    const IdList<T, H> *idlist;
 };
 
 // A list, where each element has an integer identifier. The list is kept
@@ -387,148 +401,152 @@ struct CompareId {
 // id.
 template <class T, class H>
 class IdList {
-    T *elem            = nullptr;
-    int elemsAllocated = 0;
+    std::vector<T> elemstore;
+    std::vector<int> elemidx;
+    std::vector<int> freelist;
 public:
-    int n = 0;
+    int n = 0;  // PAR@@@@@ make this private to see all interesting and suspicious places in SoveSpace ;-)
 
+    friend struct CompareId<T, H>;
     using Compare = CompareId<T, H>;
 
-    bool IsEmpty() const {
-        return n == 0;
-    }
+    struct iterator {
+        typedef std::random_access_iterator_tag iterator_category;
+        typedef T value_type;
+        typedef int difference_type;
+        typedef T *pointer;
+        typedef T &reference;
+
+    public:
+        T &operator*() const noexcept { return *elem; }
+        const T *operator->() const noexcept { return elem; }
+
+        bool operator==(const iterator &p) const { return p.position == position; }
+        bool operator!=(const iterator &p) const { return !operator==(p); }
+
+        iterator &operator++() {
+            ++position;
+            if(position >= (int)list->elemidx.size()) {
+                elem = nullptr; // PAR@@@@ Remove just debugging
+            } else if(0 <= position) {
+                elem = &(list->elemstore[list->elemidx[position]]);
+            }
+            return *this;
+        }
 
-    void AllocForOneMore() {
-        if(n >= elemsAllocated) {
-            ReserveMore((elemsAllocated + 32)*2 - n);
+        // Needed for std:find_if of gcc used in entity.cpp GenerateEquations 
+        difference_type operator-(const iterator &rhs) const noexcept {
+            return position - rhs.position;
         }
+
+        iterator(IdList<T, H> *l) : position(0), list(l) {
+            if(list) {
+                if(list->elemstore.size() && list->elemidx.size()) {
+                    elem = &(list->elemstore[list->elemidx[position]]);
+                }
+            }
+        };
+        iterator(IdList<T, H> *l, int pos) : position(pos), list(l) {
+            if(position >= (int)list->elemidx.size()) {
+                elem = nullptr;
+            } else if(0 <= position) {
+                elem = &((list->elemstore)[list->elemidx[position]]);
+            }
+        };
+
+    private:
+        int position;
+        T *elem;
+        IdList<T, H> *list;
+    };
+
+
+    bool IsEmpty() const {
+        return n == 0;
     }
 
     uint32_t MaximumId() {
         if(IsEmpty()) {
             return 0;
         } else {
-            return Last()->h.v;
+            return elemstore[elemidx.back()].h.v;
         }
     }
 
     H AddAndAssignId(T *t) {
         t->h.v = (MaximumId() + 1);
-        AllocForOneMore();
 
-        // Copy-construct at the end of the list.
-        new(&elem[n]) T(*t);
+        // Add at the end of the list.
+        elemstore.push_back(*t);
+        elemidx.push_back(elemstore.size()-1);
         ++n;
 
         return t->h;
     }
 
-    T * LowerBound(T const& t) {
-        if(IsEmpty()) {
-            return nullptr;
-        }
-        auto it = std::lower_bound(begin(), end(), t, Compare());
-        return it;
-    }
-
-    T * LowerBound(H const& h) {
-        if(IsEmpty()) {
-            return nullptr;
-        }
-        auto it = std::lower_bound(begin(), end(), h, Compare());
-        return it;
-    }
-
-    int LowerBoundIndex(T const& t) {
-        if(IsEmpty()) {
-            return 0;
-        }
-        auto it = LowerBound(t);
-        auto idx = std::distance(begin(), it);
-        auto i = static_cast<int>(idx);
-        return i;
-    }
     void ReserveMore(int howMuch) {
-        if(n + howMuch > elemsAllocated) {
-            elemsAllocated = n + howMuch;
-            T *newElem = (T *)::operator new[]((size_t)elemsAllocated*sizeof(T));
-            for(int i = 0; i < n; i++) {
-                new(&newElem[i]) T(std::move(elem[i]));
-                elem[i].~T();
-            }
-            ::operator delete[](elem);
-            elem = newElem;
-        }
+        elemstore.reserve(elemstore.size() + howMuch);
+        elemidx.reserve(elemidx.size() + howMuch);
+        //        freelist.reserve(freelist.size() + howMuch);    // PAR@@@@ maybe we should - not much more RAM
     }
 
     void Add(T *t) {
-        AllocForOneMore();
-
         // Look to see if we already have something with the same handle value.
         ssassert(FindByIdNoOops(t->h) == nullptr, "Handle isn't unique");
 
-        // Copy-construct at the end of the list.
-        new(&elem[n]) T(*t);
+        // Find out where the added element should be.
+        auto pos = std::lower_bound(elemidx.begin(), elemidx.end(), *t, Compare(this));
+
+        if(freelist.empty()) { // Add a new element to the store
+            elemstore.push_back(*t);
+            // Insert a pointer to the element at the correct position
+            if(elemidx.empty()) {
+                // The list is empty so pos, begin and end are all null.
+                // insert does not work in this case.
+                elemidx.push_back(elemstore.size()-1);
+            } else {
+                elemidx.insert(pos, elemstore.size() - 1);
+            }
+        } else { // Use the last element from the freelist
+            // Insert an index to the element at the correct position
+            elemidx.insert(pos, freelist.back());
+            // Remove the element from the freelist
+            freelist.pop_back();
+
+            // Copy-construct to the element storage.
+            elemstore[*pos] = T(*t);
+            //            *elemptr[pos] = *t;   // PAR@@@@@@ maybe this?
+        }
+
         ++n;
-        // The item we just added is trivially sorted, so "merge"
-        std::inplace_merge(begin(), end() - 1, end(), Compare());
     }
 
     T *FindById(H h) {
         T *t = FindByIdNoOops(h);
-        ssassert(t != NULL, "Cannot find handle");
+        ssassert(t != nullptr, "Cannot find handle");
         return t;
     }
 
-    int IndexOf(H h) {
-        if(IsEmpty()) {
-            return -1;
-        }
-        auto it = LowerBound(h);
-        auto idx = std::distance(begin(), it);
-        if (idx < n) {
-            return idx;
-        }
-        return -1;
-    }
-
     T *FindByIdNoOops(H h) {
         if(IsEmpty()) {
             return nullptr;
         }
-        auto it = LowerBound(h);
-        if (it == nullptr || it == end()) {
+        auto it = std::lower_bound(elemidx.begin(), elemidx.end(), h, Compare(this));
+        if(it == elemidx.end()) {
             return nullptr;
+        } else {
+            if(elemstore[*it].h.v != h.v) {
+                return nullptr;
+            }
+            return &elemstore[*it];
         }
-        if (it->h.v == h.v) {
-            return it;
-        }
-        return nullptr;
-    }
-
-    T *First() {
-        return (IsEmpty()) ? NULL : &(elem[0]);
-    }
-    T *Last() {
-        return (IsEmpty()) ? NULL : &(elem[n-1]);
-    }
-    T *NextAfter(T *prev) {
-        if(IsEmpty() || !prev) return NULL;
-        if(prev - First() == (n - 1)) return NULL;
-        return prev + 1;
     }
 
-    T &Get(size_t i) { return elem[i]; }
-    T const &Get(size_t i) const { return elem[i]; }
+    T &Get(size_t i) { return elemstore[elemidx[i]]; }
     T &operator[](size_t i) { return Get(i); }
-    T const &operator[](size_t i) const { return Get(i); }
 
-    T *begin() { return IsEmpty() ? nullptr : &elem[0]; }
-    T *end() { return IsEmpty() ? nullptr : &elem[0] + n; }
-    const T *begin() const { return IsEmpty() ? nullptr : &elem[0]; }
-    const T *end() const { return IsEmpty() ? nullptr : &elem[0] + n; }
-    const T *cbegin() const { return begin(); }
-    const T *cend() const { return end(); }
+    iterator begin() { return IsEmpty() ? nullptr : iterator(this); }
+    iterator end() { return IsEmpty() ? nullptr : iterator(this, elemidx.size()); }
 
     void ClearTags() {
         for(auto &elt : *this) { elt.tag = 0; }
@@ -545,22 +563,23 @@ public:
         int src, dest;
         dest = 0;
         for(src = 0; src < n; src++) {
-            if(elem[src].tag) {
+            if(elemstore[elemidx[src]].tag) {
                 // this item should be deleted
-                elem[src].Clear();
+                elemstore[elemidx[src]].Clear();
+//                elemstore[elemidx[src]].~T(); // Clear below calls the destructors
+                freelist.push_back(elemidx[src]);
+                elemidx[src] = 0xDEADBEEF; // PAR@@@@@ just for debugging, not needed, remove later
             } else {
                 if(src != dest) {
-                    elem[dest] = elem[src];
+                    elemidx[dest] = elemidx[src];
                 }
                 dest++;
             }
         }
-        for(int i = dest; i < n; i++)
-            elem[i].~T();
         n = dest;
-        // and elemsAllocated is untouched, because we didn't resize
+        elemidx.resize(n);  // Clear left over elements at the end.
     }
-    void RemoveById(H h) {
+    void RemoveById(H h) {  // PAR@@@@@ this can be optimized
         ClearTags();
         FindById(h)->tag = 1;
         RemoveTagged();
@@ -568,28 +587,35 @@ public:
 
     void MoveSelfInto(IdList<T,H> *l) {
         l->Clear();
-        std::swap(l->elem, elem);
-        std::swap(l->elemsAllocated, elemsAllocated);
+        std::swap(l->elemstore, elemstore);
+        std::swap(l->elemidx, elemidx);
+        std::swap(l->freelist, freelist);
         std::swap(l->n, n);
     }
 
     void DeepCopyInto(IdList<T,H> *l) {
         l->Clear();
-        l->elem = (T *)::operator new[](elemsAllocated * sizeof(elem[0]));
-        for(int i = 0; i < n; i++)
-            new(&l->elem[i]) T(elem[i]);
-        l->elemsAllocated = elemsAllocated;
+
+        for(auto const &it : elemstore) {
+            l->elemstore.push_back(it);
+        }
+
+        for(auto const &it : elemidx) {
+            l->elemidx.push_back(it);
+        }
+
         l->n = n;
     }
 
     void Clear() {
-        for(int i = 0; i < n; i++) {
-            elem[i].Clear();
-            elem[i].~T();
+        for(auto &it : elemidx) {
+            elemstore[it].Clear();
+//            elemstore[it].~T(); // clear below calls the destructors
         }
-        if(elem) ::operator delete[](elem);
-        elem = NULL;
-        elemsAllocated = n = 0;
+        freelist.clear();
+        elemidx.clear();
+        elemstore.clear();
+        n = 0;
     }
 
 };
index f5649b687dd221078aaa477df63d338d0ce1b6b3..f1c331fd787b953de1faedd91f54555e9293ab83 100644 (file)
@@ -207,7 +207,6 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool
     for(auto &entity : SK.entity) {
         Entity *e = &entity;
         if(!e->IsVisible()) continue;
-        if(e->construction) continue;
 
         if(SS.exportPwlCurves || sm || fabs(SS.exportOffset) > LENGTH_EPS)
         {
@@ -367,9 +366,9 @@ void SolveSpaceUI::ExportLinesAndMesh(SEdgeList *sel, SBezierList *sbl, SMesh *s
 
             // And calculate lighting for the triangle
             Vector n = tt.Normal().WithMagnitude(1);
-            double lighting = SS.ambientIntensity +
+            double lighting = min(1.0, SS.ambientIntensity +
                                   max(0.0, (SS.lightIntensity[0])*(n.Dot(l0))) +
-                                  max(0.0, (SS.lightIntensity[1])*(n.Dot(l1)));
+                                  max(0.0, (SS.lightIntensity[1])*(n.Dot(l1))));
             double r = min(1.0, tt.meta.color.redF()   * lighting),
                    g = min(1.0, tt.meta.color.greenF() * lighting),
                    b = min(1.0, tt.meta.color.blueF()  * lighting);
@@ -735,25 +734,22 @@ void VectorFileWriter::OutputLinesAndMesh(SBezierLoopSetSet *sblss, SMesh *sm) {
     if(sblss) {
         SBezierLoopSet *sbls;
         for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
-            SBezierLoop *sbl;
-            sbl = sbls->l.First();
-            if(!sbl) continue;
-            b = sbl->l.First();
-            if(!b || !Style::Exportable(b->auxA)) continue;
-
-            hStyle hs = { (uint32_t)b->auxA };
-            Style *stl = Style::Get(hs);
-            double lineWidth   = Style::WidthMm(b->auxA)*s;
-            RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
-            RgbaColor fillRgb   = Style::FillColor(hs, /*forExport=*/true);
-
-            StartPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
-            for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+            for(SBezierLoop *sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+                b = sbl->l.First();
+                if(!b || !Style::Exportable(b->auxA)) continue;
+
+                hStyle hs = { (uint32_t)b->auxA };
+                Style *stl = Style::Get(hs);
+                double lineWidth   = Style::WidthMm(b->auxA)*s;
+                RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
+                RgbaColor fillRgb   = Style::FillColor(hs, /*forExport=*/true);
+
+                StartPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
                 for(b = sbl->l.First(); b; b = sbl->l.NextAfter(b)) {
                     Bezier(b);
                 }
+                FinishPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
             }
-            FinishPath(strokeRgb, lineWidth, stl->filled, fillRgb, hs);
         }
     }
     FinishAndCloseFile();
@@ -956,15 +952,20 @@ void SolveSpaceUI::ExportMeshAsThreeJsTo(FILE *f, const Platform::Path &filename
     SPointList spl = {};
     STriangle *tr;
     Vector bndl, bndh;
+
+    const std::string THREE_FN("three-r111.min.js");
+    const std::string HAMMER_FN("hammer-2.0.8.js");
+    const std::string CONTROLS_FN("SolveSpaceControls.js");
+
     const char htmlbegin[] = R"(
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="utf-8"></meta>
     <title>Three.js Solvespace Mesh</title>
-    <script id="three-r76.js">%s</script>
-    <script id="hammer-2.0.8.js">%s</script>
-    <script id="SolveSpaceControls.js">%s</script>
+    <script id="%s">%s</script>
+    <script id="%s">%s</script>
+    <script id="%s">%s</script>
     <style type="text/css">
     body { margin: 0; overflow: hidden; }
     </style>
@@ -1014,9 +1015,12 @@ void SolveSpaceUI::ExportMeshAsThreeJsTo(FILE *f, const Platform::Path &filename
 
     if(filename.HasExtension("html")) {
         fprintf(f, htmlbegin,
-                LoadStringFromGzip("threejs/three-r76.js.gz").c_str(),
-                LoadStringFromGzip("threejs/hammer-2.0.8.js.gz").c_str(),
-                LoadString("threejs/SolveSpaceControls.js").c_str());
+                THREE_FN.c_str(),
+                LoadStringFromGzip("threejs/" + THREE_FN + ".gz").c_str(),
+                HAMMER_FN.c_str(),
+                LoadStringFromGzip("threejs/" + HAMMER_FN + ".gz").c_str(),
+                CONTROLS_FN.c_str(),
+                LoadString("threejs/" + CONTROLS_FN).c_str());
     }
 
     fprintf(f, "var solvespace_model_%s = {\n"
index db42dc085ee63ad6fa6e22c79a2635f3712886df..5bfa57f676003718f99850f4085587ab995b8ac6 100644 (file)
@@ -353,22 +353,21 @@ void StepFileWriter::ExportSurfacesTo(const Platform::Path &filename) {
 
     advancedFaces = {};
 
-    SSurface *ss;
-    for(ss = shell->surface.First(); ss; ss = shell->surface.NextAfter(ss)) {
-        if(ss->trim.IsEmpty())
+    for(SSurface &ss : shell->surface) {
+        if(ss.trim.IsEmpty())
             continue;
 
         // Get all of the loops of Beziers that trim our surface (with each
         // Bezier split so that we use the section as t goes from 0 to 1), and
         // the piecewise linearization of those loops in xyz space.
         SBezierList sbl = {};
-        ss->MakeSectionEdgesInto(shell, NULL, &sbl);
+        ss.MakeSectionEdgesInto(shell, NULL, &sbl);
 
         // Apply the export scale factor.
-        ss->ScaleSelfBy(1.0/SS.exportScale);
+        ss.ScaleSelfBy(1.0/SS.exportScale);
         sbl.ScaleSelfBy(1.0/SS.exportScale);
 
-        ExportSurface(ss, &sbl);
+        ExportSurface(&ss, &sbl);
 
         sbl.Clear();
     }
index 4a184abbcd8c9dc4b78b3688f449f16cc28bbbdb..55abac685e9f25f2acb0a70770547be1e77ed568 100644 (file)
@@ -170,22 +170,21 @@ public:
         }
 
         if(writer->constraint) {
-            Constraint *c;
-            for(c = writer->constraint->First(); c; c = writer->constraint->NextAfter(c)) {
-                if(!writer->NeedToOutput(c)) continue;
-                switch(c->type) {
+            for(Constraint &c : *writer->constraint) {
+                if(!writer->NeedToOutput(&c)) continue;
+                switch(c.type) {
                     case Constraint::Type::PT_PT_DISTANCE: {
-                        Vector ap = SK.GetEntity(c->ptA)->PointGetNum();
-                        Vector bp = SK.GetEntity(c->ptB)->PointGetNum();
-                        Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(c->disp.offset);
+                        Vector ap = SK.GetEntity(c.ptA)->PointGetNum();
+                        Vector bp = SK.GetEntity(c.ptB)->PointGetNum();
+                        Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(c.disp.offset);
                         writeAlignedDimension(xfrm(ap),  xfrm(bp), xfrm(ref),
-                                              xfrm(ref), c->Label(), c->GetStyle(), c->valA);
+                                              xfrm(ref), c.Label(), c.GetStyle(), c.valA);
                         break;
                     }
 
                     case Constraint::Type::PT_LINE_DISTANCE: {
-                        Vector pt = SK.GetEntity(c->ptA)->PointGetNum();
-                        Entity *line = SK.GetEntity(c->entityA);
+                        Vector pt = SK.GetEntity(c.ptA)->PointGetNum();
+                        Entity *line = SK.GetEntity(c.entityA);
                         Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
                         Vector lB = SK.GetEntity(line->point[1])->PointGetNum();
                         Vector dl = lB.Minus(lA);
@@ -194,7 +193,7 @@ public:
 
                         if(pt.Equals(closest)) break;
 
-                        Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(c->disp.offset);
+                        Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(c.disp.offset);
                         Vector refClosest = ref.ClosestPointOnLine(lA, dl);
 
                         double ddl = dl.Dot(dl);
@@ -209,54 +208,54 @@ public:
 
                         Vector xdl = xfrm(lB).Minus(xfrm(lA));
                         writeLinearDimension(xfrm(pt), xfrm(refClosest), xfrm(ref),
-                                             xfrm(ref), c->Label(),
+                                             xfrm(ref), c.Label(),
                                              atan2(xdl.y, xdl.x) / PI * 180.0 + 90.0, 0.0,
-                                             c->GetStyle(), c->valA);
+                                             c.GetStyle(), c.valA);
                         break;
                     }
 
                     case Constraint::Type::DIAMETER: {
-                        Entity *circle = SK.GetEntity(c->entityA);
+                        Entity *circle = SK.GetEntity(c.entityA);
                         Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
                         Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum();
                         Vector n = q.RotationN().WithMagnitude(1);
                         double r = circle->CircleGetRadiusNum();
 
-                        Vector ref = center.Plus(c->disp.offset);
+                        Vector ref = center.Plus(c.disp.offset);
                         // Force the label into the same plane as the circle.
                         ref = ref.Minus(n.ScaledBy(n.Dot(ref) - n.Dot(center)));
 
                         Vector rad = ref.Minus(center).WithMagnitude(r);
-                        if(/*isRadius*/c->other) {
+                        if(/*isRadius*/c.other) {
                             writeRadialDimension(
                                 xfrm(center), xfrm(center.Plus(rad)),
-                                xfrm(ref), c->Label(), c->GetStyle(), c->valA);
+                                xfrm(ref), c.Label(), c.GetStyle(), c.valA);
                         } else {
                             writeDiametricDimension(
                                 xfrm(center.Minus(rad)), xfrm(center.Plus(rad)),
-                                xfrm(ref), c->Label(), c->GetStyle(), c->valA);
+                                xfrm(ref), c.Label(), c.GetStyle(), c.valA);
                         }
                         break;
                     }
 
                     case Constraint::Type::ANGLE: {
-                        Entity *a = SK.GetEntity(c->entityA);
-                        Entity *b = SK.GetEntity(c->entityB);
+                        Entity *a = SK.GetEntity(c.entityA);
+                        Entity *b = SK.GetEntity(c.entityB);
 
                         Vector a0 = a->VectorGetStartPoint();
                         Vector b0 = b->VectorGetStartPoint();
                         Vector da = a->VectorGetNum();
                         Vector db = b->VectorGetNum();
-                        if(/*otherAngle*/c->other) {
+                        if(/*otherAngle*/c.other) {
                             a0 = a0.Plus(da);
                             da = da.ScaledBy(-1);
                         }
 
                         bool skew = false;
-                        Vector ref = c->disp.offset;
+                        Vector ref = c.disp.offset;
                         Vector pi = Vector::AtIntersectionOfLines(a0, a0.Plus(da), b0, b0.Plus(db),
                                                                   &skew);
-                        if(!skew) ref = pi.Plus(c->disp.offset);
+                        if(!skew) ref = pi.Plus(c.disp.offset);
 
                         Vector norm = da.Cross(db);
                         Vector dna = norm.Cross(da).WithMagnitude(1.0);
@@ -277,7 +276,7 @@ public:
                         Vector bisect = da.WithMagnitude(1.0).ScaledBy(cos(thetaf / 2.0)).Plus(
                                         dna.ScaledBy(sin(thetaf / 2.0)));
 
-                        ref = pi.Plus(bisect.WithMagnitude(c->disp.offset.Magnitude()));
+                        ref = pi.Plus(bisect.WithMagnitude(c.disp.offset.Magnitude()));
 
                         // Get lines again to write exact line.
                         a0 = a->VectorGetStartPoint();
@@ -287,15 +286,15 @@ public:
 
                         writeAngularDimension(
                             xfrm(a0), xfrm(a0.Plus(da)), xfrm(b0), xfrm(b0.Plus(db)), xfrm(ref),
-                            xfrm(ref), c->Label(), c->GetStyle(), c->valA);
+                            xfrm(ref), c.Label(), c.GetStyle(), c.valA);
                         break;
                     }
 
                     case Constraint::Type::COMMENT: {
-                        Style *st = SK.style.FindById(c->GetStyle());
-                        writeText(xfrm(c->disp.offset), c->Label(),
-                                  Style::TextHeight(c->GetStyle()) / SS.GW.scale,
-                                  st->textAngle, st->textOrigin, c->GetStyle());
+                        Style *st = SK.style.FindById(c.GetStyle());
+                        writeText(xfrm(c.disp.offset), c.Label(),
+                                  Style::TextHeight(c.GetStyle()) / SS.GW.scale,
+                                  st->textAngle, st->textOrigin, c.GetStyle());
                         break;
                     }
 
@@ -1083,17 +1082,18 @@ void SvgFileWriter::StartFile() {
     double sw = max(ptMax.x - ptMin.x, ptMax.y - ptMin.y) / 1000;
     fprintf(f, "stroke-width:%f;\r\n", sw);
     fprintf(f, "}\r\n");
-    for(auto &style : SK.style) {
-        Style *s = &style;
 
-        RgbaColor strokeRgb = Style::Color(s->h, /*forExport=*/true);
-        StipplePattern pattern = Style::PatternType(s->h);
-        double stippleScale = Style::StippleScaleMm(s->h);
+    auto export_style = [&](hStyle hs) {
+        Style *s = Style::Get(hs);
+        RgbaColor strokeRgb = Style::Color(hs, /*forExport=*/true);
+        RgbaColor fillRgb = Style::FillColor(hs, /*forExport=*/true);
+        StipplePattern pattern = Style::PatternType(hs);
+        double stippleScale = Style::StippleScaleMm(hs);
 
-        fprintf(f, ".s%x {\r\n", s->h.v);
+        fprintf(f, ".s%x {\r\n", hs.v);
         fprintf(f, "stroke:#%02x%02x%02x;\r\n", strokeRgb.red, strokeRgb.green, strokeRgb.blue);
         // don't know why we have to take a half of the width
-        fprintf(f, "stroke-width:%f;\r\n", Style::WidthMm(s->h.v) / 2.0);
+        fprintf(f, "stroke-width:%f;\r\n", Style::WidthMm(hs.v) / 2.0);
         fprintf(f, "stroke-linecap:round;\r\n");
         fprintf(f, "stroke-linejoin:round;\r\n");
         std::string patternStr = MakeStipplePattern(pattern, stippleScale, ',',
@@ -1101,8 +1101,19 @@ void SvgFileWriter::StartFile() {
         if(!patternStr.empty()) {
             fprintf(f, "stroke-dasharray:%s;\r\n", patternStr.c_str());
         }
-        fprintf(f, "fill:none;\r\n");
+        if(s->filled) {
+            fprintf(f, "fill:#%02x%02x%02x;\r\n", fillRgb.red, fillRgb.green, fillRgb.blue);
+        }
+        else {
+            fprintf(f, "fill:none;\r\n");
+        }
         fprintf(f, "}\r\n");
+    };
+
+    export_style({Style::NO_STYLE});
+    for(auto &style : SK.style) {
+        Style *s = &style;
+        export_style(s->h);
     }
     fprintf(f, "]]></style>\r\n");
 }
@@ -1297,9 +1308,9 @@ void GCodeFileWriter::FinishAndCloseFile() {
                         SS.MmToString(pt->p.x).c_str(), SS.MmToString(pt->p.y).c_str(),
                         SS.MmToString(SS.gCode.feed).c_str());
             }
-            // Move up to a clearance plane 5mm above the work.
+            // Move up to a clearance plane above the work.
             fprintf(f, "G00 Z%s\r\n",
-                    SS.MmToString(SS.gCode.depth < 0 ? +5 : -5).c_str());
+                    SS.MmToString(SS.gCode.safeHeight).c_str());
         }
     }
 
index 99d68ec4a4ef43d4285de0d538828b3727b594b7..d5ed87b5836ce153c373977beb38705abd0717e5 100644 (file)
@@ -400,15 +400,24 @@ Expr *Expr::PartialWrt(hParam p) const {
     ssassert(false, "Unexpected operation");
 }
 
-uint64_t Expr::ParamsUsed() const {
-    uint64_t r = 0;
-    if(op == Op::PARAM)     r |= ((uint64_t)1 << (parh.v % 61));
-    if(op == Op::PARAM_PTR) r |= ((uint64_t)1 << (parp->h.v % 61));
+void Expr::ParamsUsedList(std::vector<hParam> *list) const {
+    if(op == Op::PARAM || op == Op::PARAM_PTR) {
+        // leaf: just add ourselves if we aren't already there
+        hParam param = (op == Op::PARAM) ? parh : parp->h;
+        if(list->end() != std::find_if(list->begin(), list->end(),
+                                       [=](const hParam &p) { return p.v == param.v; })) {
+            // We found ourselves in the list already, early out.
+            return;
+        }
+        list->push_back(param);
+        return;
+    }
 
     int c = Children();
-    if(c >= 1)          r |= a->ParamsUsed();
-    if(c >= 2)          r |= b->ParamsUsed();
-    return r;
+    if(c >= 1) {
+        a->ParamsUsedList(list);
+        if(c >= 2) b->ParamsUsedList(list);
+    }
 }
 
 bool Expr::DependsOn(hParam p) const {
@@ -424,6 +433,11 @@ bool Expr::DependsOn(hParam p) const {
 bool Expr::Tol(double a, double b) {
     return fabs(a - b) < 0.001;
 }
+
+bool Expr::IsZeroConst() const {
+    return op == Op::CONSTANT && EXACT(v == 0.0);
+}
+
 Expr *Expr::FoldConstants() {
     Expr *n = AllocExpr();
     *n = *this;
index 7109cf6516ef600ee37c2e756df1caec8bb390bd..7eef4e005189ef675178432d97d2decbb821682c 100644 (file)
@@ -70,9 +70,10 @@ public:
 
     Expr *PartialWrt(hParam p) const;
     double Eval() const;
-    uint64_t ParamsUsed() const;
+    void ParamsUsedList(std::vector<hParam> *list) const;
     bool DependsOn(hParam p) const;
     static bool Tol(double a, double b);
+    bool IsZeroConst() const;
     Expr *FoldConstants();
     void Substitute(hParam oldh, hParam newh);
 
index f36e49b3411130e8fcd29b8c1966522c68e408ae..0b5806c06a0eeb05689bcef71a9697ca4c25cfb8 100644 (file)
@@ -354,19 +354,18 @@ bool SolveSpaceUI::SaveToFile(const Platform::Path &filename) {
     }
 
     SShell *s = &g->runningShell;
-    SSurface *srf;
-    for(srf = s->surface.First(); srf; srf = s->surface.NextAfter(srf)) {
+    for(SSurface &srf : s->surface) {
         fprintf(fh, "Surface %08x %08x %08x %d %d\n",
-            srf->h.v, srf->color.ToPackedInt(), srf->face, srf->degm, srf->degn);
-        for(i = 0; i <= srf->degm; i++) {
-            for(j = 0; j <= srf->degn; j++) {
+            srf.h.v, srf.color.ToPackedInt(), srf.face, srf.degm, srf.degn);
+        for(i = 0; i <= srf.degm; i++) {
+            for(j = 0; j <= srf.degn; j++) {
                 fprintf(fh, "SCtrl %d %d %.20f %.20f %.20f Weight %20.20f\n",
-                    i, j, CO(srf->ctrl[i][j]), srf->weight[i][j]);
+                    i, j, CO(srf.ctrl[i][j]), srf.weight[i][j]);
             }
         }
 
         STrimBy *stb;
-        for(stb = srf->trim.First(); stb; stb = srf->trim.NextAfter(stb)) {
+        for(stb = srf.trim.First(); stb; stb = srf.trim.NextAfter(stb)) {
             fprintf(fh, "TrimBy %08x %d %.20f %.20f %.20f  %.20f %.20f %.20f\n",
                 stb->curve.v, stb->backwards ? 1 : 0,
                 CO(stb->start), CO(stb->finish));
@@ -374,21 +373,20 @@ bool SolveSpaceUI::SaveToFile(const Platform::Path &filename) {
 
         fprintf(fh, "AddSurface\n");
     }
-    SCurve *sc;
-    for(sc = s->curve.First(); sc; sc = s->curve.NextAfter(sc)) {
+    for(SCurve &sc : s->curve) {
         fprintf(fh, "Curve %08x %d %d %08x %08x\n",
-            sc->h.v,
-            sc->isExact ? 1 : 0, sc->exact.deg,
-            sc->surfA.v, sc->surfB.v);
+            sc.h.v,
+            sc.isExact ? 1 : 0, sc.exact.deg,
+            sc.surfA.v, sc.surfB.v);
 
-        if(sc->isExact) {
-            for(i = 0; i <= sc->exact.deg; i++) {
+        if(sc.isExact) {
+            for(i = 0; i <= sc.exact.deg; i++) {
                 fprintf(fh, "CCtrl %d %.20f %.20f %.20f Weight %.20f\n",
-                    i, CO(sc->exact.ctrl[i]), sc->exact.weight[i]);
+                    i, CO(sc.exact.ctrl[i]), sc.exact.weight[i]);
             }
         }
         SCurvePt *scpt;
-        for(scpt = sc->pts.First(); scpt; scpt = sc->pts.NextAfter(scpt)) {
+        for(scpt = sc.pts.First(); scpt; scpt = sc.pts.NextAfter(scpt)) {
             fprintf(fh, "CurvePt %d %.20f %.20f %.20f\n",
                 scpt->vertex ? 1 : 0, CO(scpt->p));
         }
@@ -468,6 +466,7 @@ void SolveSpaceUI::LoadUsingTable(const Platform::Path &filename, char *key, cha
 }
 
 bool SolveSpaceUI::LoadFromFile(const Platform::Path &filename, bool canCancel) {
+    bool fileIsEmpty = true;
     allConsistent = false;
     fileLoadError = false;
 
@@ -485,6 +484,8 @@ bool SolveSpaceUI::LoadFromFile(const Platform::Path &filename, bool canCancel)
 
     char line[1024];
     while(fgets(line, (int)sizeof(line), fh)) {
+        fileIsEmpty = false;
+
         char *s = strchr(line, '\n');
         if(s) *s = '\0';
         // We should never get files with \r characters in them, but mailers
@@ -545,6 +546,11 @@ bool SolveSpaceUI::LoadFromFile(const Platform::Path &filename, bool canCancel)
 
     fclose(fh);
 
+    if(fileIsEmpty) {
+        Error(_("The file is empty. It may be corrupt."));
+        NewFile();
+    }
+
     if(fileLoadError) {
         Error(_("Unrecognized data in file. This file may be corrupt, or "
                 "from a newer version of the program."));
@@ -704,7 +710,9 @@ bool SolveSpaceUI::LoadEntitiesFromFile(const Platform::Path &filename, EntityLi
                                         SMesh *m, SShell *sh)
 {
     if(strcmp(filename.Extension().c_str(), "emn")==0) {
-        return LinkIDF(filename, le, m, sh);    
+        return LinkIDF(filename, le, m, sh);
+    } else if(strcmp(filename.Extension().c_str(), "stl")==0) {
+        return LinkStl(filename, le, m, sh);    
     } else {
         return LoadEntitiesFromSlvs(filename, le, m, sh);
     }
@@ -901,6 +909,8 @@ try_again:
                     return false;
                 }
             }
+            if(g.IsTriangleMeshAssembly())
+                g.forceToMesh = true;
         } else if(linkMap.count(g.linkFile) == 0) {
             dbp("Missing file for group: %s", g.name.c_str());
             // The file was moved; prompt the user for its new location.
index fdda9946253f67558377154691bbcc2cc7646837..fdb19b8032133667443ae392cc60c8c31641e27a 100644 (file)
@@ -224,9 +224,11 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
         if(PruneGroups(hg))
             goto pruned;
 
+        int groupRequestIndex = 0;
         for(auto &req : SK.request) {
             Request *r = &req;
             if(r->group != hg) continue;
+            r->groupRequestIndex = groupRequestIndex++;
 
             r->Generate(&(SK.entity), &(SK.param));
         }
@@ -548,8 +550,11 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
 }
 
 SolveResult SolveSpaceUI::TestRankForGroup(hGroup hg, int *rank) {
-    WriteEqSystemForGroup(hg);
     Group *g = SK.GetGroup(hg);
+    // If we don't calculate dof or redundant is allowed, there is
+    // no point to solve rank because this result is not meaningful
+    if(g->suppressDofCalculation || g->allowRedundant) return SolveResult::OKAY;
+    WriteEqSystemForGroup(hg);
     SolveResult result = sys.SolveRank(g, rank);
     FreeAllTemporary();
     return result;
index 32b4b082e1f14e57a3f4354f4b7b2a1c7f91242c..98ed54d6863fe9a69d5b2e22325af89ecc937dd5 100644 (file)
@@ -94,10 +94,12 @@ const MenuEntry Menu[] = {
 { 1, N_("Show Snap &Grid"),             Command::SHOW_GRID,        '>',     KC, mView  },
 { 1, N_("Darken Inactive Solids"),      Command::DIM_SOLID_MODEL,  0,       KC, mView  },
 { 1, N_("Use &Perspective Projection"), Command::PERSPECTIVE_PROJ, '`',     KC, mView  },
+{ 1, N_("Show E&xploded View"),         Command::EXPLODE_SKETCH,   '\\',    KC, mView  },
 { 1, N_("Dimension &Units"),            Command::NONE,             0,       KN, NULL  },
 { 2, N_("Dimensions in &Millimeters"),  Command::UNITS_MM,         0,       KR, mView },
 { 2, N_("Dimensions in M&eters"),       Command::UNITS_METERS,     0,       KR, mView },
 { 2, N_("Dimensions in &Inches"),       Command::UNITS_INCHES,     0,       KR, mView },
+{ 2, N_("Dimensions in &Feet and Inches"), Command::UNITS_FEET_INCHES, 0,   KR, mView },
 { 1,  NULL,                             Command::NONE,             0,       KN, NULL   },
 { 1, N_("Show &Toolbar"),               Command::SHOW_TOOLBAR,     0,       KC, mView  },
 { 1, N_("Show Property Bro&wser"),      Command::SHOW_TEXT_WND,    '\t',    KC, mView  },
@@ -153,8 +155,8 @@ const MenuEntry Menu[] = {
 { 1, NULL,                              Command::NONE,             0,       KN, NULL   },
 { 1, N_("&On Point / Curve / Plane"),   Command::ON_ENTITY,        'o',     KN, mCon   },
 { 1, N_("E&qual Length / Radius / Angle"), Command::EQUAL,         'q',     KN, mCon   },
-{ 1, N_("Length Ra&tio"),               Command::RATIO,            'z',     KN, mCon   },
-{ 1, N_("Length Diff&erence"),          Command::DIFFERENCE,       'j',     KN, mCon   },
+{ 1, N_("Length / Arc Ra&tio"),         Command::RATIO,            'z',     KN, mCon   },
+{ 1, N_("Length / Arc Diff&erence"),    Command::DIFFERENCE,       'j',     KN, mCon   },
 { 1, N_("At &Midpoint"),                Command::AT_MIDPOINT,      'm',     KN, mCon   },
 { 1, N_("S&ymmetric"),                  Command::SYMMETRIC,        'y',     KN, mCon   },
 { 1, N_("Para&llel / Tangent"),         Command::PARALLEL,         'l',     KN, mCon   },
@@ -181,6 +183,7 @@ const MenuEntry Menu[] = {
 { 0, N_("&Help"),                       Command::NONE,             0,       KN, mHelp  },
 { 1, N_("&Language"),                   Command::LOCALE,           0,       KN, mHelp  },
 { 1, N_("&Website / Manual"),           Command::WEBSITE,          0,       KN, mHelp  },
+{ 1, N_("&Go to GitHub commit"),        Command::GITHUB,            0,       KN, mHelp  },
 #ifndef __APPLE__
 { 1, N_("&About"),                      Command::ABOUT,            0,       KN, mHelp  },
 #endif
@@ -317,6 +320,8 @@ void GraphicsWindow::PopulateMainMenu() {
                 dimSolidModelMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::PERSPECTIVE_PROJ) {
                 perspectiveProjMenuItem = menuItem;
+            } else if(Menu[i].cmd == Command::EXPLODE_SKETCH) {
+                explodeMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::SHOW_TOOLBAR) {
                 showToolbarMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::SHOW_TEXT_WND) {
@@ -329,6 +334,8 @@ void GraphicsWindow::PopulateMainMenu() {
                 unitsMetersMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::UNITS_INCHES) {
                 unitsInchesMenuItem = menuItem;
+            } else if(Menu[i].cmd == Command::UNITS_FEET_INCHES) {
+                unitsFeetInchesMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::SEL_WORKPLANE) {
                 inWorkplaneMenuItem = menuItem;
             } else if(Menu[i].cmd == Command::FREE_IN_3D) {
@@ -369,8 +376,11 @@ static void PopulateMenuWithPathnames(Platform::MenuRef menu,
 
 void GraphicsWindow::PopulateRecentFiles() {
     PopulateMenuWithPathnames(openRecentMenu, SS.recentFiles, [](const Platform::Path &path) {
+        // OkayToStartNewFile could mutate recentFiles, which will invalidate path (which is a
+        // reference into the recentFiles vector), so take a copy of it here.
+        Platform::Path pathCopy(path);
         if(!SS.OkayToStartNewFile()) return;
-        SS.Load(path);
+        SS.Load(pathCopy);
     });
 
     PopulateMenuWithPathnames(linkRecentMenu, SS.recentFiles, [](const Platform::Path &path) {
@@ -404,6 +414,8 @@ void GraphicsWindow::Init() {
     showEdges = true;
     showMesh = false;
     showOutlines = false;
+    showFacesDrawing = false;
+    showFacesNonDrawing = true;
     drawOccludedAs = DrawOccludedAs::INVISIBLE;
 
     showTextWindow = true;
@@ -419,7 +431,7 @@ void GraphicsWindow::Init() {
             using namespace std::placeholders;
             // Do this first, so that if it causes an onRender event we don't try to paint without
             // a canvas.
-            window->SetMinContentSize(720, 670);
+            window->SetMinContentSize(720, /*ToolbarDrawOrHitTest 636*/ 32 * 18 + 3 * 16 + 8 + 4);
             window->onClose = std::bind(&SolveSpaceUI::MenuFile, Command::EXIT);
             window->onRender = std::bind(&GraphicsWindow::Paint, this);
             window->onKeyboardEvent = std::bind(&GraphicsWindow::KeyboardEvent, this, _1);
@@ -700,16 +712,47 @@ double GraphicsWindow::ZoomToFit(const Camera &camera,
     return scale;
 }
 
+
+void GraphicsWindow::ZoomToMouse(double zoomMultiplyer) {
+    double offsetRight = offset.Dot(projRight);
+    double offsetUp    = offset.Dot(projUp);
+
+    double width, height;
+    window->GetContentSize(&width, &height);
+
+    double righti = currentMousePosition.x / scale - offsetRight;
+    double upi    = currentMousePosition.y / scale - offsetUp;
+
+    // zoomMultiplyer of 1 gives a default zoom factor of 1.2x: zoomMultiplyer * 1.2
+    // zoom = adjusted zoom negative zoomMultiplyer will zoom out, positive will zoom in
+    //
+
+    scale *= exp(0.1823216 * zoomMultiplyer); // ln(1.2) = 0.1823216
+
+    double rightf = currentMousePosition.x / scale - offsetRight;
+    double upf    = currentMousePosition.y / scale - offsetUp;
+
+    offset = offset.Plus(projRight.ScaledBy(rightf - righti));
+    offset = offset.Plus(projUp.ScaledBy(upf - upi));
+
+    if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) {
+        if(havePainted) {
+            SS.ScheduleShowTW();
+        }
+    }
+    havePainted = false;
+    Invalidate();
+}
+
+
 void GraphicsWindow::MenuView(Command id) {
     switch(id) {
         case Command::ZOOM_IN:
-            SS.GW.scale *= 1.2;
-            SS.ScheduleShowTW();
+            SS.GW.ZoomToMouse(1);
             break;
 
         case Command::ZOOM_OUT:
-            SS.GW.scale /= 1.2;
-            SS.ScheduleShowTW();
+            SS.GW.ZoomToMouse(-1);
             break;
 
         case Command::ZOOM_TO_FIT:
@@ -745,6 +788,12 @@ void GraphicsWindow::MenuView(Command id) {
             }
             break;
 
+        case Command::EXPLODE_SKETCH:
+            SS.explode = !SS.explode;
+            SS.GW.EnsureValidActives();
+            SS.MarkGroupDirty(SS.GW.activeGroup, true);
+            break;
+
         case Command::ONTO_WORKPLANE:
             if(SS.GW.LockedInWorkplane()) {
                 SS.GW.AnimateOntoWorkplane();
@@ -838,6 +887,12 @@ void GraphicsWindow::MenuView(Command id) {
             SS.GW.EnsureValidActives();
             break;
 
+        case Command::UNITS_FEET_INCHES:
+            SS.viewUnits = Unit::FEET_INCHES;
+            SS.ScheduleShowTW();
+            SS.GW.EnsureValidActives();
+            break;
+
         case Command::UNITS_MM:
             SS.viewUnits = Unit::MM;
             SS.ScheduleShowTW();
@@ -920,6 +975,7 @@ void GraphicsWindow::EnsureValidActives() {
         case Unit::MM:
         case Unit::METERS:
         case Unit::INCHES:
+        case Unit::FEET_INCHES:
             break;
         default:
             SS.viewUnits = Unit::MM;
@@ -928,6 +984,7 @@ void GraphicsWindow::EnsureValidActives() {
     unitsMmMenuItem->SetActive(SS.viewUnits == Unit::MM);
     unitsMetersMenuItem->SetActive(SS.viewUnits == Unit::METERS);
     unitsInchesMenuItem->SetActive(SS.viewUnits == Unit::INCHES);
+    unitsFeetInchesMenuItem->SetActive(SS.viewUnits == Unit::FEET_INCHES);
 
     if(SS.TW.window) SS.TW.window->SetVisible(SS.GW.showTextWindow);
     showTextWndMenuItem->SetActive(SS.GW.showTextWindow);
@@ -935,6 +992,7 @@ void GraphicsWindow::EnsureValidActives() {
     showGridMenuItem->SetActive(SS.GW.showSnapGrid);
     dimSolidModelMenuItem->SetActive(SS.GW.dimSolidModel);
     perspectiveProjMenuItem->SetActive(SS.usePerspectiveProj);
+    explodeMenuItem->SetActive(SS.explode);
     showToolbarMenuItem->SetActive(SS.showToolbar);
     fullScreenMenuItem->SetActive(SS.GW.window->IsFullScreen());
 
@@ -965,20 +1023,19 @@ void GraphicsWindow::ForceTextWindowShown() {
 }
 
 void GraphicsWindow::DeleteTaggedRequests() {
-    Request *r;
     // Delete any requests that were affected by this deletion.
-    for(r = SK.request.First(); r; r = SK.request.NextAfter(r)) {
-        if(r->workplane == Entity::FREE_IN_3D) continue;
-        if(!r->workplane.isFromRequest()) continue;
-        Request *wrkpl = SK.GetRequest(r->workplane.request());
+    for(Request &r : SK.request) {
+        if(r.workplane == Entity::FREE_IN_3D) continue;
+        if(!r.workplane.isFromRequest()) continue;
+        Request *wrkpl = SK.GetRequest(r.workplane.request());
         if(wrkpl->tag)
-            r->tag = 1;
+            r.tag = 1;
     }
     // Rewrite any point-coincident constraints that were affected by this
     // deletion.
-    for(r = SK.request.First(); r; r = SK.request.NextAfter(r)) {
-        if(!r->tag) continue;
-        FixConstraintsForRequestBeingDeleted(r->h);
+    for(Request &r : SK.request) {
+        if(!r.tag) continue;
+        FixConstraintsForRequestBeingDeleted(r.h);
     }
     // and then delete the tagged requests.
     SK.request.RemoveTagged();
@@ -1042,9 +1099,8 @@ void GraphicsWindow::MenuEdit(Command id) {
             SS.centerOfMass.draw = false;
             // This clears the marks drawn to indicate which points are
             // still free to drag.
-            Param *p;
-            for(p = SK.param.First(); p; p = SK.param.NextAfter(p)) {
-                p->free = false;
+            for(Param &p : SK.param) {
+                p.free = false;
             }
             if(SS.exportMode) {
                 SS.exportMode = false;
@@ -1054,13 +1110,12 @@ void GraphicsWindow::MenuEdit(Command id) {
             break;
 
         case Command::SELECT_ALL: {
-            Entity *e;
-            for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-                if(e->group != SS.GW.activeGroup) continue;
-                if(e->IsFace() || e->IsDistance()) continue;
-                if(!e->IsVisible()) continue;
+            for(Entity &e : SK.entity) {
+                if(e.group != SS.GW.activeGroup) continue;
+                if(e.IsFace() || e.IsDistance()) continue;
+                if(!e.IsVisible()) continue;
 
-                SS.GW.MakeSelected(e->h);
+                SS.GW.MakeSelected(e.h);
             }
             SS.GW.Invalidate();
             SS.ScheduleShowTW();
@@ -1068,24 +1123,23 @@ void GraphicsWindow::MenuEdit(Command id) {
         }
 
         case Command::SELECT_CHAIN: {
-            Entity *e;
             int newlySelected = 0;
             bool didSomething;
             do {
                 didSomething = false;
-                for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-                    if(e->group != SS.GW.activeGroup) continue;
-                    if(!e->HasEndpoints()) continue;
-                    if(!e->IsVisible()) continue;
+                for(Entity &e : SK.entity) {
+                    if(e.group != SS.GW.activeGroup) continue;
+                    if(!e.HasEndpoints()) continue;
+                    if(!e.IsVisible()) continue;
 
-                    Vector st = e->EndpointStart(),
-                           fi = e->EndpointFinish();
+                    Vector st = e.EndpointStart(),
+                           fi = e.EndpointFinish();
 
                     bool onChain = false, alreadySelected = false;
                     List<Selection> *ls = &(SS.GW.selection);
                     for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) {
                         if(!s->entity.v) continue;
-                        if(s->entity == e->h) {
+                        if(s->entity == e.h) {
                             alreadySelected = true;
                             continue;
                         }
@@ -1102,7 +1156,7 @@ void GraphicsWindow::MenuEdit(Command id) {
                         }
                     }
                     if(onChain && !alreadySelected) {
-                        SS.GW.MakeSelected(e->h);
+                        SS.GW.MakeSelected(e.h);
                         newlySelected++;
                         didSomething = true;
                     }
@@ -1304,6 +1358,20 @@ c:
             break;
 
         case Command::CONSTRUCTION: {
+            // if we are drawing
+            if(SS.GW.pending.operation == Pending::DRAGGING_NEW_POINT ||
+               SS.GW.pending.operation == Pending::DRAGGING_NEW_LINE_POINT ||
+               SS.GW.pending.operation == Pending::DRAGGING_NEW_ARC_POINT ||
+               SS.GW.pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT ||
+               SS.GW.pending.operation == Pending::DRAGGING_NEW_RADIUS) {
+                for(auto &hr : SS.GW.pending.requests) {
+                    Request* r = SK.GetRequest(hr);
+                    r->construction = !(r->construction);
+                    SS.MarkGroupDirty(r->group);
+                }
+                SS.GW.Invalidate();
+                break;
+            }
             SS.GW.GroupSelection();
             if(SS.GW.gs.entities == 0) {
                 Error(_("No entities are selected. Select entities before "
@@ -1353,6 +1421,14 @@ void GraphicsWindow::ToggleBool(bool *v) {
         SS.GenerateAll(SolveSpaceUI::Generate::UNTIL_ACTIVE);
     }
 
+    if(v == &showFaces) {
+        if(g->type == Group::Type::DRAWING_WORKPLANE || g->type == Group::Type::DRAWING_3D) {
+            showFacesDrawing = showFaces;
+        } else {
+            showFacesNonDrawing = showFaces;
+        }
+    }
+
     Invalidate(/*clearPersistent=*/true);
     SS.ScheduleShowTW();
 }
index 1539e68c7031860d720010b04b6a8b270ee7045d..529fce646cf3c1828faa2aa60db9a0395d7be304 100644 (file)
@@ -136,14 +136,30 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
                         g.predef.negateV = wrkplg->predef.negateV;
                     } else if(wrkplg->subtype == Subtype::WORKPLANE_BY_POINT_ORTHO) {
                         g.predef.q = wrkplg->predef.q;
+                    } else if(wrkplg->subtype == Subtype::WORKPLANE_BY_POINT_NORMAL) {
+                        g.predef.q = wrkplg->predef.q;
+                        g.predef.entityB = wrkplg->predef.entityB;
                     } else ssassert(false, "Unexpected workplane subtype");
                 }
+            } else if(gs.anyNormals == 1 && gs.points == 1 && gs.n == 2) {
+                g.subtype       = Subtype::WORKPLANE_BY_POINT_NORMAL;
+                g.predef.entityB = gs.anyNormal[0];
+                g.predef.q      = SK.GetEntity(gs.anyNormal[0])->NormalGetNum();
+                g.predef.origin = gs.point[0];
+            //} else if(gs.faces == 1 && gs.points == 1 && gs.n == 2) {
+            //    g.subtype = Subtype::WORKPLANE_BY_POINT_FACE;
+            //    g.predef.q      = SK.GetEntity(gs.face[0])->NormalGetNum();
+            //    g.predef.origin = gs.point[0];
             } else {
                 Error(_("Bad selection for new sketch in workplane. This "
                         "group can be created with:\n\n"
                         "    * a point (through the point, orthogonal to coordinate axes)\n"
                         "    * a point and two line segments (through the point, "
-                               "parallel to the lines)\n"
+                        "parallel to the lines)\n"
+                        "    * a point and a normal (through the point, "
+                        "orthogonal to the normal)\n"
+                        /*"    * a point and a face (through the point, "
+                        "parallel to the face)\n"*/
                         "    * a workplane (copy of the workplane)\n"));
                 return;
             }
@@ -392,7 +408,11 @@ bool Group::IsForcedToMeshBySource() const {
 }
 
 bool Group::IsForcedToMesh() const {
-    return forceToMesh || IsForcedToMeshBySource();
+    return forceToMesh || IsTriangleMeshAssembly() || IsForcedToMeshBySource();
+}
+
+bool Group::IsTriangleMeshAssembly() const {
+    return type == Type::LINKED && linkFile.Extension() == "stl";
 }
 
 std::string Group::DescriptionString() {
@@ -404,11 +424,10 @@ std::string Group::DescriptionString() {
 }
 
 void Group::Activate() {
-    if(type == Type::EXTRUDE || type == Type::LINKED || type == Type::LATHE ||
-       type == Type::REVOLVE || type == Type::HELIX || type == Type::TRANSLATE || type == Type::ROTATE) {
-        SS.GW.showFaces = true;
+    if(type == Type::DRAWING_WORKPLANE || type == Type::DRAWING_3D) {
+        SS.GW.showFaces = SS.GW.showFacesDrawing;
     } else {
-        SS.GW.showFaces = false;
+        SS.GW.showFaces = SS.GW.showFacesNonDrawing;
     }
     SS.MarkGroupDirty(h); // for good measure; shouldn't be needed
     SS.ScheduleShowTW();
@@ -443,11 +462,14 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
             } else if(subtype == Subtype::WORKPLANE_BY_POINT_ORTHO) {
                 // Already given, numerically.
                 q = predef.q;
+            } else if(subtype == Subtype::WORKPLANE_BY_POINT_NORMAL) {
+                q = SK.GetEntity(predef.entityB)->NormalGetNum();
             } else ssassert(false, "Unexpected workplane subtype");
 
             Entity normal = {};
             normal.type = Entity::Type::NORMAL_N_COPY;
             normal.numNormal = q;
+
             normal.point[0] = h.entity(2);
             normal.group = h;
             normal.h = h.entity(1);
@@ -800,6 +822,12 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *l) {
         AddEq(l, (EC(axis.z))->Minus(EP(6)), 5);
 #undef EC
 #undef EP
+        if(type == Type::HELIX) {
+            if(valB != 0.0) {
+                AddEq(l, Expr::From(h.param(7))->Times(Expr::From(PI))->
+                Minus(Expr::From(h.param(3))->Times(Expr::From(valB))), 6);
+            }
+        }
     } else if(type == Type::EXTRUDE) {
         if(predef.entityB != Entity::FREE_IN_3D) {
             // The extrusion path is locked along a line, normal to the
@@ -1172,3 +1200,6 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
     el->Add(&en);
 }
 
+bool Group::ShouldDrawExploded() const {
+    return SS.explode && h == SS.GW.activeGroup && type == Type::DRAWING_WORKPLANE && !SS.exportMode;
+}
index f1041d632f4729d5890e46314fc19170eb5cb9f0..11add4f11171c4e4b731dc62458aa04e70413c03 100644 (file)
@@ -83,13 +83,12 @@ void Group::GenerateLoops() {
 }
 
 void SShell::RemapFaces(Group *g, int remap) {
-    SSurface *ss;
-    for(ss = surface.First(); ss; ss = surface.NextAfter(ss)){
-        hEntity face = { ss->face };
+    for(SSurface &ss : surface){
+        hEntity face = { ss.face };
         if(face == Entity::NO_ENTITY) continue;
 
         face = g->Remap(face, remap);
-        ss->face = face.v;
+        ss.face = face.v;
     }
 }
 
@@ -292,13 +291,12 @@ void Group::GenerateShellAndMesh() {
                 // So these are the sides
                 if(ss->degm != 1 || ss->degn != 1) continue;
 
-                Entity *e;
-                for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-                    if(e->group != opA) continue;
-                    if(e->type != Entity::Type::LINE_SEGMENT) continue;
+                for(Entity &e : SK.entity) {
+                    if(e.group != opA) continue;
+                    if(e.type != Entity::Type::LINE_SEGMENT) continue;
 
-                    Vector a = SK.GetEntity(e->point[0])->PointGetNum(),
-                           b = SK.GetEntity(e->point[1])->PointGetNum();
+                    Vector a = SK.GetEntity(e.point[0])->PointGetNum(),
+                           b = SK.GetEntity(e.point[1])->PointGetNum();
                     a = a.Plus(ttop);
                     b = b.Plus(ttop);
                     // Could get taken backwards, so check all cases.
@@ -307,7 +305,7 @@ void Group::GenerateShellAndMesh() {
                        (a.Equals(ss->ctrl[0][1]) && b.Equals(ss->ctrl[1][1])) ||
                        (b.Equals(ss->ctrl[0][1]) && a.Equals(ss->ctrl[1][1])))
                     {
-                        face = Remap(e->h, REMAP_LINE_TO_FACE);
+                        face = Remap(e.h, REMAP_LINE_TO_FACE);
                         ss->face = face.v;
                         break;
                     }
index 1789e5cc1c1e7476bf0c6235da1ce2b5108dc8c5..3cd501c850166ffe653be58e60e21883bb9838f6 100644 (file)
@@ -54,7 +54,7 @@ static std::vector <std::string> splitString(const std::string line) {
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// Functions for linking an IDF file - we need to create entites that
+// Functions for linking an IDF file - we need to create entities that
 // get remapped into a linked group similar to linking .slvs files
 //////////////////////////////////////////////////////////////////////////////
 
@@ -77,7 +77,7 @@ static hEntity newPoint(EntityList *el, int *id, Vector p, bool visible = true)
     return en.h;
 }
 
-static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) {
+static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1, bool keepout) {
     Entity en = {};
     en.type = Entity::Type::LINE_SEGMENT;
     en.point[0] = p0;
@@ -85,8 +85,8 @@ static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) {
     en.extraPoints = 0;
     en.timesApplied = 0;
     en.group.v = 493;
-    en.construction = false;
-    en.style.v = Style::ACTIVE_GRP;
+    en.construction = keepout;
+    en.style.v = keepout? Style::CONSTRUCTION : Style::ACTIVE_GRP;
     en.actVisible = true;
     en.forceHidden = false;
 
@@ -117,7 +117,7 @@ static hEntity newNormal(EntityList *el, int *id, Quaternion normal) {
     return en.h;
 }
 
-static hEntity newArc(EntityList *el, int *id, hEntity p0, hEntity p1, hEntity pc, hEntity hnorm) {
+static hEntity newArc(EntityList *el, int *id, hEntity p0, hEntity p1, hEntity pc, hEntity hnorm, bool keepout) {
     Entity en = {};
     en.type = Entity::Type::ARC_OF_CIRCLE;
     en.point[0] = pc;
@@ -127,8 +127,8 @@ static hEntity newArc(EntityList *el, int *id, hEntity p0, hEntity p1, hEntity p
     en.extraPoints = 0;
     en.timesApplied = 0;
     en.group.v = 403;
-    en.construction = false;
-    en.style.v = Style::ACTIVE_GRP;
+    en.construction = keepout;
+    en.style.v = keepout? Style::CONSTRUCTION : Style::ACTIVE_GRP;
     en.actVisible = true;
     en.forceHidden = false;    *id = *id+1;
 
@@ -158,7 +158,7 @@ static hEntity newDistance(EntityList *el, int *id, double distance) {
     return en.h;
 }
 
-static hEntity newCircle(EntityList *el, int *id, hEntity p0, hEntity hdist, hEntity hnorm) {
+static hEntity newCircle(EntityList *el, int *id, hEntity p0, hEntity hdist, hEntity hnorm, bool keepout) {
     Entity en = {};
     en.type = Entity::Type::CIRCLE;
     en.point[0] = p0;
@@ -167,8 +167,8 @@ static hEntity newCircle(EntityList *el, int *id, hEntity p0, hEntity hdist, hEn
     en.extraPoints = 0;
     en.timesApplied = 0;
     en.group.v = 399;
-    en.construction = false;
-    en.style.v = Style::ACTIVE_GRP;
+    en.construction = keepout;
+    en.style.v = keepout? Style::CONSTRUCTION : Style::ACTIVE_GRP;
     en.actVisible = true;
     en.forceHidden = false;
 
@@ -196,18 +196,18 @@ static Vector ArcCenter(Vector p0, Vector p1, double angle) {
 // Positive angles are counter clockwise, negative are clockwise. An angle of 360
 // indicates a circle centered at x1,y1 passing through x2,y2 and is a complete loop.
 static void CreateEntity(EntityList *el, int *id, hEntity h0, hEntity h1, hEntity hnorm,
-                    Vector p0, Vector p1, double angle) {
+                    Vector p0, Vector p1, double angle, bool keepout) {
     if (angle == 0.0) {
         //line
         if(p0.Equals(p1)) return;
 
-        newLine(el, id, h0, h1);
+        newLine(el, id, h0, h1, keepout);
 
     } else if(angle == 360.0) {
         // circle
         double d = p1.Minus(p0).Magnitude();
         hEntity hd = newDistance(el, id, d);
-        newCircle(el, id, h1, hd, hnorm);
+        newCircle(el, id, h1, hd, hnorm, keepout);
         
     } else {
         // arc
@@ -226,7 +226,7 @@ static void CreateEntity(EntityList *el, int *id, hEntity h0, hEntity h1, hEntit
         }
         Vector c = m.Minus(perp.ScaledBy(dist));
         hEntity hc = newPoint(el, id, c, /*visible=*/false);
-        newArc(el, id, h0, h1, hc, hnorm);
+        newArc(el, id, h0, h1, hc, hnorm, keepout);
     }
 }
 
@@ -291,9 +291,9 @@ static void MakeBeziersForArcs(SBezierList *sbl, Vector center, Vector pa, Vecto
 namespace SolveSpace {
 
 // Here we read the important section of an IDF file. SolveSpace Entities are directly created by
-// the funcions above, which is only OK because of the way linking works. For example points do
+// the functions above, which is only OK because of the way linking works. For example points do
 // not have handles for solver parameters (coordinates), they only have their actPoint values
-// set (or actNormal or actDistance). These are incompete entites and would be a problem if
+// set (or actNormal or actDistance). These are incomplete entities and would be a problem if
 // they were part of the sketch, but they are not. After making a list of them here, a new group
 // gets created from copies of these. Those copies are complete and part of the sketch group.
 bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *sh) {
@@ -332,8 +332,9 @@ bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s
     
     double board_thickness = 10.0;
     double scale = 1.0; //mm
-    bool topEntities, bottomEntities;
-    
+    bool topEntities       = false;
+    bool bottomEntities    = false;
+
     Quaternion normal = Quaternion::From(Vector::From(1,0,0), Vector::From(0,1,0));
     hEntity hnorm = newNormal(el, &entityCount, normal);
 
@@ -355,10 +356,9 @@ bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s
                 } else if (line.find(".BOARD_OUTLINE") == 0) {
                     section = board_outline;
                     record_number = 1;
-// no keepouts for now - they should also be shown as construction?
-//                } else if (line.find(".ROUTE_KEEPOUT") == 0) {
-//                    section = routing_keepout;
-//                    record_number = 1;
+                } else if (line.find(".ROUTE_KEEPOUT") == 0) {
+                    section = routing_keepout;
+                    record_number = 1;
                 } else if(line.find(".DRILLED_HOLES") == 0) {
                     section = drilled_holes;
                     record_number = 1;
@@ -433,13 +433,15 @@ bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s
                         bool vis = (ang == 360.0);
                         if (bottomEntities) {
                             hEntity hp = newPoint(el, &entityCount, point, /*visible=*/vis);
-                            CreateEntity(el, &entityCount, hprev, hp, hnorm, pprev, point, ang);
+                            CreateEntity(el, &entityCount, hprev, hp, hnorm, pprev, point, ang,
+                                (section == routing_keepout) );
                             pprev = point;
                             hprev = hp;
                         }
                         if (topEntities) {
                             hEntity hp = newPoint(el, &entityCount, pTop, /*visible=*/vis);
-                            CreateEntity(el, &entityCount, hprevTop, hp, hnorm, pprevTop, pTop, ang);
+                            CreateEntity(el, &entityCount, hprevTop, hp, hnorm, pprevTop, pTop,
+                                 ang, (section == routing_keepout) );
                             pprevTop = pTop;
                             hprevTop = hp;
                         }
@@ -467,12 +469,12 @@ bool LinkIDF(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *s
                         Vector cent = Vector::From(x,y,0.0);
                         hEntity hcent = newPoint(el, &entityCount, cent);
                         hEntity hdist = newDistance(el, &entityCount, d/2);
-                        newCircle(el, &entityCount, hcent, hdist, hnorm);
+                        newCircle(el, &entityCount, hcent, hdist, hnorm, false);
                         // and again for the top
                         Vector cTop = Vector::From(x,y,board_thickness);
                         hcent = newPoint(el, &entityCount, cTop);
                         hdist = newDistance(el, &entityCount, d/2);
-                        newCircle(el, &entityCount, hcent, hdist, hnorm);
+                        newCircle(el, &entityCount, hcent, hdist, hnorm, false);
                         // create the curves for the extrusion
                         Vector pt = Vector::From(x+d/2, y, 0.0);
                         MakeBeziersForArcs(&sbl, cent, pt, pt, normal, 360.0);
diff --git a/src/importmesh.cpp b/src/importmesh.cpp
new file mode 100644 (file)
index 0000000..f06a8f1
--- /dev/null
@@ -0,0 +1,256 @@
+//-----------------------------------------------------------------------------
+// Triangle mesh file reader. Reads an STL file triangle mesh and creates
+// a SovleSpace SMesh from it. Supports only Linking, not import.
+//
+// Copyright 2020 Paul Kahler.
+//-----------------------------------------------------------------------------
+#include "solvespace.h"
+#include "sketch.h"
+#include <vector>
+
+#define MIN_POINT_DISTANCE 0.001
+
+// we will check for duplicate vertices and keep all their normals
+class vertex {
+public:
+    Vector p;
+    std::vector<Vector> normal;
+};
+
+static bool isEdgeVertex(vertex &v) {
+    unsigned int i,j;
+    bool result = false;
+    for(i=0;i<v.normal.size();i++) {
+        for(j=i;j<v.normal.size();j++) {
+            if(v.normal[i].Dot(v.normal[j]) < 0.9) {
+                result = true;
+            }
+        }
+    }
+    return result;
+}
+// This function has poor performance, used inside a loop it is O(n**2)
+static void addUnique(std::vector<vertex> &lv, Vector &p, Vector &n) {
+    unsigned int i;
+    for(i=0; i<lv.size(); i++) {
+        if(lv[i].p.Equals(p, MIN_POINT_DISTANCE)) {
+            break;
+        }
+    }
+    if(i==lv.size()) {
+        vertex v;
+        v.p = p;
+        lv.push_back(v);
+    }
+    // we could improve a little by only storing unique normals
+    lv[i].normal.push_back(n);
+};
+
+// Make a new point - type doesn't matter since we will make a copy later
+static hEntity newPoint(EntityList *el, int *id, Vector p) {
+    Entity en = {};
+    en.type = Entity::Type::POINT_N_COPY;
+    en.extraPoints = 0;
+    en.timesApplied = 0;
+    en.group.v = 462;
+    en.actPoint = p;
+    en.construction = false;
+    en.style.v = Style::DATUM;
+    en.actVisible = true;
+    en.forceHidden = false;
+
+    en.h.v = *id + en.group.v*65536; 
+    *id = *id+1;   
+    el->Add(&en);
+    return en.h;
+}
+
+// check if a vertex is unique and add it via newPoint if it is.
+static void addVertex(EntityList *el, Vector v) {
+    if(el->n < 15000) {
+        int id = el->n;
+        newPoint(el, &id, v);
+    }
+}
+
+static hEntity newNormal(EntityList *el, int *id, Quaternion normal, hEntity p) {
+    // normals have parameters, but we don't need them to make a NORMAL_N_COPY from this
+    Entity en = {};
+    en.type = Entity::Type::NORMAL_N_COPY;
+    en.extraPoints = 0;
+    en.timesApplied = 0;
+    en.group.v = 472;
+    en.actNormal = normal;
+    en.construction = false;
+    en.style.v = Style::NORMALS;
+    // to be visible we need to add a point.
+//    en.point[0] = newPoint(el, id, Vector::From(0,0,0));
+    en.point[0] = p;
+    en.actVisible = true;
+    en.forceHidden = false;
+
+    *id = *id+1;
+    en.h.v = *id + en.group.v*65536;    
+    el->Add(&en);
+    return en.h;
+}
+
+static hEntity newLine(EntityList *el, int *id, hEntity p0, hEntity p1) {
+    Entity en = {};
+    en.type = Entity::Type::LINE_SEGMENT;
+    en.point[0] = p0;
+    en.point[1] = p1;
+    en.extraPoints = 0;
+    en.timesApplied = 0;
+    en.group.v = 493;
+    en.construction = true;
+    en.style.v = Style::CONSTRUCTION;
+    en.actVisible = true;
+    en.forceHidden = false;
+
+    en.h.v = *id + en.group.v*65536;
+    *id = *id + 1;
+    el->Add(&en);
+    return en.h;
+}
+
+namespace SolveSpace {
+
+bool LinkStl(const Platform::Path &filename, EntityList *el, SMesh *m, SShell *sh) {
+    dbp("\nLink STL triangle mesh.");
+    el->Clear();
+    std::string data;
+    if(!ReadFile(filename, &data)) {
+        Error("Couldn't read from '%s'", filename.raw.c_str());
+        return false;
+    }
+    
+    std::stringstream f(data);
+
+    char str[80] = {};
+    f.read(str, 80);
+    
+    if(0==memcmp("solid", str, 5)) {
+    // just returning false will trigger the warning that linked file is not present
+    // best solution is to add an importer for text STL.
+        Message(_("Text-formated STL files are not currently supported"));
+        return false;
+    }
+    
+    uint32_t n;
+    uint32_t color;
+    
+    f.read((char*)&n, 4);
+    dbp("%d triangles", n);
+    
+    float x,y,z;
+    float xn,yn,zn;
+    
+    std::vector<vertex> verts = {};
+    
+    for(uint32_t i = 0; i<n; i++) {
+        STriangle tr = {};
+
+        // read the triangle normal
+        f.read((char*)&xn, 4);
+        f.read((char*)&yn, 4);
+        f.read((char*)&zn, 4);
+        tr.an = Vector::From(xn,yn,zn);
+        tr.bn = tr.an;
+        tr.cn = tr.an;
+
+        f.read((char*)&x, 4);
+        f.read((char*)&y, 4);
+        f.read((char*)&z, 4);
+        tr.a.x = x;
+        tr.a.y = y;
+        tr.a.z = z;
+
+        f.read((char*)&x, 4);
+        f.read((char*)&y, 4);
+        f.read((char*)&z, 4);
+        tr.b.x = x;
+        tr.b.y = y;
+        tr.b.z = z;
+
+        f.read((char*)&x, 4);
+        f.read((char*)&y, 4);
+        f.read((char*)&z, 4);
+        tr.c.x = x;
+        tr.c.y = y;
+        tr.c.z = z;
+
+        f.read((char*)&color,2);
+        if(color & 0x8000) {
+            tr.meta.color.red = (color >> 7) & 0xf8;
+            tr.meta.color.green = (color >> 2) & 0xf8;
+            tr.meta.color.blue = (color << 3);
+            tr.meta.color.alpha = 255;
+        } else {
+            tr.meta.color.red = 90;
+            tr.meta.color.green = 120;
+            tr.meta.color.blue = 140;
+            tr.meta.color.alpha = 255;        
+        }
+
+        m->AddTriangle(&tr);
+        Vector normal = tr.Normal().WithMagnitude(1.0);
+        addUnique(verts, tr.a, normal);
+        addUnique(verts, tr.b, normal);
+        addUnique(verts, tr.c, normal);
+    }
+    dbp("%d vertices", verts.size());
+
+    int id = 1;
+
+    //add the STL origin and normals
+    hEntity origin = newPoint(el, &id, Vector::From(0.0, 0.0, 0.0));    
+    newNormal(el, &id, Quaternion::From(Vector::From(1,0,0),Vector::From(0,1,0)), origin);
+    newNormal(el, &id, Quaternion::From(Vector::From(0,1,0),Vector::From(0,0,1)), origin);
+    newNormal(el, &id, Quaternion::From(Vector::From(0,0,1),Vector::From(1,0,0)), origin);
+
+    BBox box = {};
+    box.minp = verts[0].p;
+    box.maxp = verts[0].p;
+
+    // determine the bounding box for all vertexes
+    for(unsigned int i=1; i<verts.size(); i++) {
+        box.Include(verts[i].p);
+    }
+
+    hEntity p[8];
+    p[0] = newPoint(el, &id, Vector::From(box.minp.x, box.minp.y, box.minp.z));
+    p[1] = newPoint(el, &id, Vector::From(box.maxp.x, box.minp.y, box.minp.z));
+    p[2] = newPoint(el, &id, Vector::From(box.minp.x, box.maxp.y, box.minp.z));
+    p[3] = newPoint(el, &id, Vector::From(box.maxp.x, box.maxp.y, box.minp.z));
+    p[4] = newPoint(el, &id, Vector::From(box.minp.x, box.minp.y, box.maxp.z));
+    p[5] = newPoint(el, &id, Vector::From(box.maxp.x, box.minp.y, box.maxp.z));
+    p[6] = newPoint(el, &id, Vector::From(box.minp.x, box.maxp.y, box.maxp.z));
+    p[7] = newPoint(el, &id, Vector::From(box.maxp.x, box.maxp.y, box.maxp.z));
+
+    newLine(el, &id, p[0], p[1]);
+    newLine(el, &id, p[0], p[2]);
+    newLine(el, &id, p[3], p[1]);
+    newLine(el, &id, p[3], p[2]);
+
+    newLine(el, &id, p[4], p[5]);
+    newLine(el, &id, p[4], p[6]);
+    newLine(el, &id, p[7], p[5]);
+    newLine(el, &id, p[7], p[6]);
+
+    newLine(el, &id, p[0], p[4]);
+    newLine(el, &id, p[1], p[5]);
+    newLine(el, &id, p[2], p[6]);
+    newLine(el, &id, p[3], p[7]);
+    
+    for(unsigned int i=0; i<verts.size(); i++) {
+        // create point entities for edge vertexes
+        if(isEdgeVertex(verts[i])) {
+           addVertex(el, verts[i].p);
+        }
+    }
+
+    return true;
+}
+
+}
index b0d8e1d6c6d65f79b38102f520c52c70910610d6..9da18b04717df1ce8437c09580b67723cb3d0d82 100644 (file)
@@ -131,11 +131,15 @@ case SLVS_C_PT_ON_LINE:         t = Constraint::Type::PT_ON_LINE; break;
 case SLVS_C_PT_ON_FACE:         t = Constraint::Type::PT_ON_FACE; break;
 case SLVS_C_EQUAL_LENGTH_LINES: t = Constraint::Type::EQUAL_LENGTH_LINES; break;
 case SLVS_C_LENGTH_RATIO:       t = Constraint::Type::LENGTH_RATIO; break;
+case SLVS_C_ARC_ARC_LEN_RATIO:  t = Constraint::Type::ARC_ARC_LEN_RATIO; break;
+case SLVS_C_ARC_LINE_LEN_RATIO: t = Constraint::Type::ARC_LINE_LEN_RATIO; break;
 case SLVS_C_EQ_LEN_PT_LINE_D:   t = Constraint::Type::EQ_LEN_PT_LINE_D; break;
 case SLVS_C_EQ_PT_LN_DISTANCES: t = Constraint::Type::EQ_PT_LN_DISTANCES; break;
 case SLVS_C_EQUAL_ANGLE:        t = Constraint::Type::EQUAL_ANGLE; break;
 case SLVS_C_EQUAL_LINE_ARC_LEN: t = Constraint::Type::EQUAL_LINE_ARC_LEN; break;
 case SLVS_C_LENGTH_DIFFERENCE:  t = Constraint::Type::LENGTH_DIFFERENCE; break;
+case SLVS_C_ARC_ARC_DIFFERENCE: t = Constraint::Type::ARC_ARC_DIFFERENCE; break;
+case SLVS_C_ARC_LINE_DIFFERENCE:t = Constraint::Type::ARC_LINE_DIFFERENCE; break;
 case SLVS_C_SYMMETRIC:          t = Constraint::Type::SYMMETRIC; break;
 case SLVS_C_SYMMETRIC_HORIZ:    t = Constraint::Type::SYMMETRIC_HORIZ; break;
 case SLVS_C_SYMMETRIC_VERT:     t = Constraint::Type::SYMMETRIC_VERT; break;
index 94b247878e0cae4a6b84310a9f1caa98ddbee739..99cb48bbeb7397db81468639f8006145c0e4f021 100644 (file)
@@ -50,38 +50,36 @@ void GraphicsWindow::FixConstraintsForRequestBeingDeleted(hRequest hr) {
     Request *r = SK.GetRequest(hr);
     if(r->group != SS.GW.activeGroup) return;
 
-    Entity *e;
-    for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-        if(!(e->h.isFromRequest())) continue;
-        if(e->h.request() != hr) continue;
+    for(Entity &e : SK.entity) {
+        if(!(e.h.isFromRequest())) continue;
+        if(e.h.request() != hr) continue;
 
-        if(e->type != Entity::Type::POINT_IN_2D &&
-           e->type != Entity::Type::POINT_IN_3D)
+        if(e.type != Entity::Type::POINT_IN_2D &&
+           e.type != Entity::Type::POINT_IN_3D)
         {
             continue;
         }
 
         // This is a point generated by the request being deleted; so fix
         // the constraints for that.
-        FixConstraintsForPointBeingDeleted(e->h);
+        FixConstraintsForPointBeingDeleted(e.h);
     }
 }
 void GraphicsWindow::FixConstraintsForPointBeingDeleted(hEntity hpt) {
     List<hEntity> ld = {};
 
-    Constraint *c;
     SK.constraint.ClearTags();
-    for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
-        if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
-        if(c->group != SS.GW.activeGroup) continue;
+    for(Constraint &c : SK.constraint) {
+        if(c.type != Constraint::Type::POINTS_COINCIDENT) continue;
+        if(c.group != SS.GW.activeGroup) continue;
 
-        if(c->ptA == hpt) {
-            ld.Add(&(c->ptB));
-            c->tag = 1;
+        if(c.ptA == hpt) {
+            ld.Add(&(c.ptB));
+            c.tag = 1;
         }
-        if(c->ptB == hpt) {
-            ld.Add(&(c->ptA));
-            c->tag = 1;
+        if(c.ptB == hpt) {
+            ld.Add(&(c.ptA));
+            c.tag = 1;
         }
     }
     // Remove constraints without waiting for regeneration; this way
@@ -225,21 +223,21 @@ void GraphicsWindow::ParametricCurve::CreateRequestTrimmedTo(double t,
 // happens to exist, then constrain that point coincident to hpt.
 //-----------------------------------------------------------------------------
 void GraphicsWindow::ParametricCurve::ConstrainPointIfCoincident(hEntity hpt) {
-    Entity *e, *pt;
+    Entity *pt;
     pt = SK.GetEntity(hpt);
     Vector ev, ptv;
     ptv = pt->PointGetNum();
 
-    for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
-        if(e->h == pt->h) continue;
-        if(!e->IsPoint()) continue;
-        if(e->group != pt->group) continue;
-        if(e->workplane != pt->workplane) continue;
+    for(Entity &e : SK.entity) {
+        if(e.h == pt->h) continue;
+        if(!e.IsPoint()) continue;
+        if(e.group != pt->group) continue;
+        if(e.workplane != pt->workplane) continue;
 
-        ev = e->PointGetNum();
+        ev = e.PointGetNum();
         if(!ev.Equals(ptv)) continue;
 
-        Constraint::ConstrainCoincident(hpt, e->h);
+        Constraint::ConstrainCoincident(hpt, e.h);
         break;
     }
 }
index 729c8ee2c14470a8389f35c4854d3f4eac9bd81e..d183f58a0ffc87a18bbf534c993913d40ab4430f 100644 (file)
@@ -10,6 +10,8 @@ void GraphicsWindow::UpdateDraggedPoint(hEntity hp, double mx, double my) {
     Vector pos = p->PointGetNum();
     UpdateDraggedNum(&pos, mx, my);
     p->PointForceTo(pos);
+
+    SS.ScheduleShowTW();
 }
 
 void GraphicsWindow::UpdateDraggedNum(Vector *pos, double mx, double my) {
@@ -101,7 +103,10 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
         shiftDown = !shiftDown;
     }
 
-    if(SS.showToolbar) {
+    // Not passing right-button and middle-button drags to the toolbar avoids
+    // some cosmetic issues with trackpad pans/rotates implemented with
+    // simulated right-button drag events causing spurious hover events.
+    if(SS.showToolbar && !middleDown) {
         if(ToolbarMouseMoved((int)x, (int)y)) {
             hover.Clear();
             return;
@@ -188,32 +193,23 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
             hEntity dragEntity = ChooseFromHoverToDrag().entity;
             if(dragEntity.v) e = SK.GetEntity(dragEntity);
             if(e && e->type != Entity::Type::WORKPLANE) {
-                Entity *e = SK.GetEntity(dragEntity);
+                if(!hoverWasSelectedOnMousedown) {
+                    // The user clicked an unselected entity, which
+                    // means they're dragging just the hovered thing,
+                    // not the full selection. So clear all the selection
+                    // except that entity.
+                    ClearSelection();
+                    MakeSelected(dragEntity);
+                }
                 if(e->type == Entity::Type::CIRCLE && selection.n <= 1) {
                     // Drag the radius.
-                    ClearSelection();
                     pending.circle = dragEntity;
                     pending.operation = Pending::DRAGGING_RADIUS;
                 } else if(e->IsNormal()) {
-                    ClearSelection();
                     pending.normal = dragEntity;
                     pending.operation = Pending::DRAGGING_NORMAL;
                 } else {
-                    if(!hoverWasSelectedOnMousedown) {
-                        // The user clicked an unselected entity, which
-                        // means they're dragging just the hovered thing,
-                        // not the full selection. So clear all the selection
-                        // except that entity.
-                        ClearSelection();
-                        MakeSelected(e->h);
-                    }
                     StartDraggingBySelection();
-                    if(!hoverWasSelectedOnMousedown) {
-                        // And then clear the selection again, since they
-                        // probably didn't want that selected if they just
-                        // were dragging it.
-                        ClearSelection();
-                    }
                     hover.Clear();
                     pending.operation = Pending::DRAGGING_POINTS;
                 }
@@ -270,15 +266,16 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
         return;
     }
 
+    if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
+        SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
+        SS.extraLine.ptB = UnProjectPoint(mp);
+        SS.extraLine.draw = true;
+    }
+
     // We're currently dragging something; so do that. But if we haven't
     // painted since the last time we solved, do nothing, because there's
     // no sense solving a frame and not displaying it.
     if(!havePainted) {
-        if(pending.operation == Pending::DRAGGING_POINTS && ctrlDown) {
-            SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
-            SS.extraLine.ptB = UnProjectPoint(mp);
-            SS.extraLine.draw = true;
-        }
         return;
     }
 
@@ -305,7 +302,6 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
             HitTestMakeSelection(mp);
             SS.MarkGroupDirtyByEntity(pending.point);
             orig.mouse = mp;
-            Invalidate();
             break;
 
         case Pending::DRAGGING_POINTS:
@@ -320,20 +316,16 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
                         // Don't start dragging the position about the normal
                         // until we're a little ways out, to get a reasonable
                         // reference pos
-                        orig.mouse = mp;
-                        break;
+                        qt = Quaternion::IDENTITY;
+                    } else {
+                        double theta = atan2(orig.mouse.y-orig.mouseOnButtonDown.y,
+                                             orig.mouse.x-orig.mouseOnButtonDown.x);
+                        theta -= atan2(y-orig.mouseOnButtonDown.y,
+                                       x-orig.mouseOnButtonDown.x);
+
+                        Vector gn = projRight.Cross(projUp);
+                        qt = Quaternion::From(gn, -theta);
                     }
-                    double theta = atan2(orig.mouse.y-orig.mouseOnButtonDown.y,
-                                         orig.mouse.x-orig.mouseOnButtonDown.x);
-                    theta -= atan2(y-orig.mouseOnButtonDown.y,
-                                   x-orig.mouseOnButtonDown.x);
-
-                    Vector gn = projRight.Cross(projUp);
-                    qt = Quaternion::From(gn, -theta);
-
-                    SS.extraLine.draw = true;
-                    SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
-                    SS.extraLine.ptB = UnProjectPoint(mp);
                 } else {
                     double dx = -(x - orig.mouse.x);
                     double dy = -(y - orig.mouse.y);
@@ -341,7 +333,6 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
                     qt = Quaternion::From(projUp,   -s*dx).Times(
                          Quaternion::From(projRight, s*dy));
                 }
-                orig.mouse = mp;
 
                 // Now apply this rotation to the points being dragged.
                 List<hEntity> *lhe = &(pending.points);
@@ -354,18 +345,18 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
                             p = qt.Rotate(p);
                             p = p.Plus(SS.extraLine.ptA);
                             e->PointForceTo(p);
-                            SS.MarkGroupDirtyByEntity(e->h);
+                        } else {
+                            UpdateDraggedPoint(*he, x, y);
                         }
-                        continue;
+                    } else {
+                        Quaternion q = e->PointGetQuaternion();
+                        Vector     p = e->PointGetNum();
+                        q = qt.Times(q);
+                        e->PointForceQuaternionTo(q);
+                        // Let's rotate about the selected point; so fix up the
+                        // translation so that that point didn't move.
+                        e->PointForceTo(p);
                     }
-
-                    Quaternion q = e->PointGetQuaternion();
-                    Vector     p = e->PointGetNum();
-                    q = qt.Times(q);
-                    e->PointForceQuaternionTo(q);
-                    // Let's rotate about the selected point; so fix up the
-                    // translation so that that point didn't move.
-                    e->PointForceTo(p);
                     SS.MarkGroupDirtyByEntity(e->h);
                 }
             } else {
@@ -374,8 +365,8 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
                     UpdateDraggedPoint(*he, x, y);
                     SS.MarkGroupDirtyByEntity(*he);
                 }
-                orig.mouse = mp;
             }
+            orig.mouse = mp;
             break;
 
         case Pending::DRAGGING_NEW_CUBIC_POINT: {
@@ -430,6 +421,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
             SK.GetEntity(circle->distance)->DistanceForceTo(r);
 
             SS.MarkGroupDirtyByEntity(pending.circle);
+            SS.ScheduleShowTW();
             break;
         }
 
@@ -531,11 +523,16 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
     }
 
     if(pending.operation == Pending::DRAGGING_NEW_LINE_POINT ||
-       pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT)
+       pending.operation == Pending::DRAGGING_NEW_CUBIC_POINT ||
+       pending.operation == Pending::DRAGGING_NEW_ARC_POINT ||
+       pending.operation == Pending::DRAGGING_NEW_RADIUS ||
+       pending.operation == Pending::DRAGGING_NEW_POINT
+       )
     {
         // Special case; use a right click to stop drawing lines, since
         // a left click would draw another one. This is quicker and more
-        // intuitive than hitting escape. Likewise for new cubic segments.
+        // intuitive than hitting escape. Likewise for other entities
+        // for consistency.
         ClearPending();
         return;
     }
@@ -719,11 +716,12 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
 
         if(gs.points == 1) {
             Entity *p = SK.GetEntity(gs.point[0]);
-            Constraint *c;
+            Constraint *c = nullptr;
             IdList<Constraint,hConstraint> *lc = &(SK.constraint);
-            for(c = lc->First(); c; c = lc->NextAfter(c)) {
-                if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
-                if(c->ptA == p->h || c->ptB == p->h) {
+            for(Constraint &ci : *lc) {
+                if(ci.type != Constraint::Type::POINTS_COINCIDENT) continue;
+                if(ci.ptA == p->h || ci.ptB == p->h) {
+                    c = &ci;
                     break;
                 }
             }
@@ -733,11 +731,10 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
 
                     SS.UndoRemember();
                     SK.constraint.ClearTags();
-                    Constraint *c;
-                    for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
-                        if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
-                        if(c->ptA == p->h || c->ptB == p->h) {
-                            c->tag = 1;
+                    for(Constraint &c : SK.constraint) {
+                        if(c.type != Constraint::Type::POINTS_COINCIDENT) continue;
+                        if(c.ptA == p->h || c.ptB == p->h) {
+                            c.tag = 1;
                         }
                     }
                     SK.constraint.RemoveTagged();
@@ -917,7 +914,7 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) {
             break;
 
         case MouseEvent::Type::SCROLL_VERT:
-            this->MouseScroll(event.x, event.y, event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta);
+            this->MouseScroll(event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta);
             break;
 
         case MouseEvent::Type::LEAVE:
@@ -1043,6 +1040,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct
                     ConstrainPointByHovered(hr.entity(1), &mouse);
 
                     ClearSuper();
+                    AddToPending(hr);
 
                     pending.operation = Pending::DRAGGING_NEW_RADIUS;
                     pending.circle = hr.entity(0);
@@ -1310,15 +1308,20 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct
 
 void GraphicsWindow::MouseLeftUp(double mx, double my, bool shiftDown, bool ctrlDown) {
     orig.mouseDown = false;
-    hoverWasSelectedOnMousedown = false;
 
     switch(pending.operation) {
         case Pending::DRAGGING_POINTS:
-            SS.extraLine.draw = false;
-            // fall through
         case Pending::DRAGGING_CONSTRAINT:
         case Pending::DRAGGING_NORMAL:
         case Pending::DRAGGING_RADIUS:
+            if(!hoverWasSelectedOnMousedown) {
+                // And then clear the selection again, since they
+                // probably didn't want that selected if they just
+                // were dragging it.
+                ClearSelection();
+            }
+            hoverWasSelectedOnMousedown = false;
+            SS.extraLine.draw = false;
             ClearPending();
             Invalidate();
             break;
@@ -1373,12 +1376,12 @@ void GraphicsWindow::EditConstraint(hConstraint constraint) {
                 value /= 2;
 
             // Try showing value with default number of digits after decimal first.
-            if(c->type == Constraint::Type::LENGTH_RATIO) {
+            if(c->type == Constraint::Type::LENGTH_RATIO || c->type == Constraint::Type::ARC_ARC_LEN_RATIO || c->type == Constraint::Type::ARC_LINE_LEN_RATIO) {
                 editValue = ssprintf("%.3f", value);
             } else if(c->type == Constraint::Type::ANGLE) {
                 editValue = SS.DegreeToString(value);
             } else {
-                editValue = SS.MmToString(value);
+                editValue = SS.MmToString(value, true);
                 value /= SS.MmPerUnit();
             }
             // If that's not enough to represent it exactly, show the value with as many
@@ -1434,7 +1437,9 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
             case Constraint::Type::PT_LINE_DISTANCE:
             case Constraint::Type::PT_FACE_DISTANCE:
             case Constraint::Type::PT_PLANE_DISTANCE:
-            case Constraint::Type::LENGTH_DIFFERENCE: {
+            case Constraint::Type::LENGTH_DIFFERENCE:
+            case Constraint::Type::ARC_ARC_DIFFERENCE:
+            case Constraint::Type::ARC_LINE_DIFFERENCE: {
                 // The sign is not displayed to the user, but this is a signed
                 // distance internally. To flip the sign, the user enters a
                 // negative distance.
@@ -1448,6 +1453,8 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
             }
             case Constraint::Type::ANGLE:
             case Constraint::Type::LENGTH_RATIO:
+            case Constraint::Type::ARC_ARC_LEN_RATIO:
+            case Constraint::Type::ARC_LINE_LEN_RATIO:
                 // These don't get the units conversion for distance, and
                 // they're always positive
                 c->valA = fabs(e->Eval());
@@ -1471,17 +1478,10 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
     }
 }
 
-void GraphicsWindow::MouseScroll(double x, double y, double delta) {
-    double offsetRight = offset.Dot(projRight);
-    double offsetUp = offset.Dot(projUp);
-
-    double righti = x/scale - offsetRight;
-    double upi = y/scale - offsetUp;
-
-    // The default zoom factor is 1.2x for one scroll wheel click (delta==1).
+void GraphicsWindow::MouseScroll(double zoomMultiplyer) {
     // To support smooth scrolling where scroll wheel events come in increments
     // smaller (or larger) than 1 we do:
-    //     scale *= exp(ln(1.2) * delta);
+    //     scale *= exp(ln(1.2) * zoomMultiplyer);
     // to ensure that the same total scroll delta always results in the same
     // total zoom irrespective of in how many increments the zoom was applied.
     // For example if we scroll a total delta of a+b in two events vs. one then
@@ -1489,21 +1489,7 @@ void GraphicsWindow::MouseScroll(double x, double y, double delta) {
     // while
     //     scale * a * b != scale * (a+b)
     // So this constant is ln(1.2) = 0.1823216 to make the default zoom 1.2x
-    scale *= exp(0.1823216 * delta);
-
-    double rightf = x/scale - offsetRight;
-    double upf = y/scale - offsetUp;
-
-    offset = offset.Plus(projRight.ScaledBy(rightf - righti));
-    offset = offset.Plus(projUp.ScaledBy(upf - upi));
-
-    if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) {
-        if(havePainted) {
-            SS.ScheduleShowTW();
-        }
-    }
-    havePainted = false;
-    Invalidate();
+    ZoomToMouse(zoomMultiplyer);
 }
 
 void GraphicsWindow::MouseLeave() {
index 61b20db1818e6170ffb10fe36797adb85073c260..70b6919b07620539a8bc3453fc4f2ea3a067faa0 100644 (file)
@@ -4,6 +4,7 @@
 // Copyright 2016 whitequark
 //-----------------------------------------------------------------------------
 #include "solvespace.h"
+#include "config.h"
 
 static void ShowUsage(const std::string &cmd) {
     fprintf(stderr, "Usage: %s <command> <options> <filename> [filename...]", cmd.c_str());
@@ -29,6 +30,8 @@ Common options:
         Whether to export the background colour in vector formats. Defaults to off.
 
 Commands:
+    version
+        Prints the current solvespace version.
     thumbnail --output <pattern> --size <size> --view <direction>
               [--chord-tol <tolerance>]
         Outputs a rendered view of the sketch, like the SolveSpace GUI would.
@@ -174,7 +177,10 @@ static bool RunCommand(const std::vector<std::string> args) {
     };
 
     unsigned width = 0, height = 0;
-    if(args[1] == "thumbnail") {
+    if(args[1] == "version") {
+        fprintf(stderr, "SolveSpace version %s \n\n", PACKAGE_VERSION);
+        return false;
+    } else if(args[1] == "thumbnail") {
         auto ParseSize = [&](size_t &argn) {
             if(argn + 1 < args.size() && args[argn] == "--size") {
                 argn++;
index 28fded44c0ab3767a1deaf92a26f19c89c95be78..0c9637ff4e220750b74cca4e6b3de90417e9db0d 100644 (file)
@@ -86,8 +86,10 @@ std::vector<FileFilter> SolveSpaceModelFileFilters = {
 };
 
 std::vector<FileFilter> SolveSpaceLinkFileFilters = {
+    { CN_("file-type", "ALL"), { "slvs", "emn", "stl" } },
     { CN_("file-type", "SolveSpace models"), { "slvs" } },
     { CN_("file-type", "IDF circuit board"), { "emn" } },
+    { CN_("file-type", "STL triangle mesh"), { "stl" } },
 };
 
 std::vector<FileFilter> RasterFileFilters = {
index 1608a6f21785b2d22900c89c9e41df4c72836c83..f63fa80b6fd96f02c071b28b4e9a27d31d3e1b1a 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef SOLVESPACE_GUI_H
 #define SOLVESPACE_GUI_H
 
+namespace SolveSpace {
 class RgbaColor;
 
 namespace Platform {
@@ -386,5 +387,6 @@ void ExitGui();
 void ClearGui();
 
 }
+} // namespace SolveSpace
 
 #endif
index e8113ed227687ae2f193b45fca997b2558b551bc..1a11582e10e6d6e9b01490c109eda06b06526e90 100644 (file)
 
 #if defined(HAVE_SPACEWARE)
 #   include <spnav.h>
-#   include <gdk/gdkx.h>
+#   include <gdk/gdk.h>
+#   if defined(GDK_WINDOWING_X11)
+#       include <gdk/gdkx.h>
+#   endif
+#   if defined(GDK_WINDOWING_WAYLAND)
+#       include <gdk/gdkwayland.h>
+#   endif
+#   if GTK_CHECK_VERSION(3, 20, 0)
+#       include <gdkmm/seat.h>
+#   else
+#       include <gdkmm/devicemanager.h>
+#   endif
 #endif
 
 #include "solvespace.h"
@@ -217,6 +228,10 @@ public:
             }
             return false;
         };
+        // Note: asan warnings about new-delete-type-mismatch are false positives here:
+        // https://gitlab.gnome.org/GNOME/gtkmm/-/issues/65
+        // Pass new_delete_type_mismatch=0 to ASAN_OPTIONS to disable those warnings.
+        // Unfortunately they won't go away until upgrading to gtkmm4
         _connection = Glib::signal_timeout().connect(handler, milliseconds);
     }
 };
@@ -963,16 +978,17 @@ public:
     }
 
     void SetCursor(Cursor cursor) override {
-        Gdk::CursorType gdkCursorType;
+        std::string cursor_name;
         switch(cursor) {
-            case Cursor::POINTER: gdkCursorType = Gdk::ARROW; break;
-            case Cursor::HAND:    gdkCursorType = Gdk::HAND1; break;
+            case Cursor::POINTER: cursor_name = "default"; break;
+            case Cursor::HAND:    cursor_name = "pointer"; break;
             default: ssassert(false, "Unexpected cursor");
         }
 
         auto gdkWindow = gtkWindow.get_gl_widget().get_window();
         if(gdkWindow) {
-            gdkWindow->set_cursor(Gdk::Cursor::create(gdkCursorType));
+            gdkWindow->set_cursor(Gdk::Cursor::create(gdkWindow->get_display(), cursor_name.c_str()));
+//        gdkWindow->get_display()
         }
     }
 
@@ -1037,16 +1053,8 @@ WindowRef CreateWindow(Window::Kind kind, WindowRef parentWindow) {
 void Open3DConnexion() {}
 void Close3DConnexion() {}
 
-#if defined(HAVE_SPACEWARE) && defined(GDK_WINDOWING_X11)
-static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gdkXEvent, GdkEvent *gdkEvent, gpointer data) {
-    XEvent *xEvent = (XEvent *)gdkXEvent;
-    WindowImplGtk *window = (WindowImplGtk *)data;
-
-    spnav_event spnavEvent;
-    if(!spnav_x11_event(xEvent, &spnavEvent)) {
-        return GDK_FILTER_CONTINUE;
-    }
-
+#if defined(HAVE_SPACEWARE) && (defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND))
+static void ProcessSpnavEvent(WindowImplGtk *window, const spnav_event &spnavEvent, bool shiftDown, bool controlDown) {
     switch(spnavEvent.type) {
         case SPNAV_EVENT_MOTION: {
             SixDofEvent event = {};
@@ -1057,8 +1065,8 @@ static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gdkXEvent, GdkEvent *gdkEvent,
             event.rotationX    = (double)spnavEvent.motion.rx *  0.001;
             event.rotationY    = (double)spnavEvent.motion.ry *  0.001;
             event.rotationZ    = (double)spnavEvent.motion.rz * -0.001;
-            event.shiftDown    = xEvent->xmotion.state & ShiftMask;
-            event.controlDown  = xEvent->xmotion.state & ControlMask;
+            event.shiftDown    = shiftDown;
+            event.controlDown  = controlDown;
             if(window->onSixDofEvent) {
                 window->onSixDofEvent(event);
             }
@@ -1074,17 +1082,52 @@ static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gdkXEvent, GdkEvent *gdkEvent,
             }
             switch(spnavEvent.button.bnum) {
                 case 0:  event.button = SixDofEvent::Button::FIT; break;
-                default: return GDK_FILTER_REMOVE;
+                default: return;
             }
-            event.shiftDown   = xEvent->xmotion.state & ShiftMask;
-            event.controlDown = xEvent->xmotion.state & ControlMask;
+            event.shiftDown   = shiftDown;
+            event.controlDown = controlDown;
             if(window->onSixDofEvent) {
                 window->onSixDofEvent(event);
             }
             break;
     }
+}
+
+static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gdkXEvent, GdkEvent *gdkEvent, gpointer data) {
+    XEvent *xEvent = (XEvent *)gdkXEvent;
+    WindowImplGtk *window = (WindowImplGtk *)data;
+    bool shiftDown   = (xEvent->xmotion.state & ShiftMask)   != 0;
+    bool controlDown = (xEvent->xmotion.state & ControlMask) != 0;
+
+    spnav_event spnavEvent;
+    if(spnav_x11_event(xEvent, &spnavEvent)) {
+        ProcessSpnavEvent(window, spnavEvent, shiftDown, controlDown);
+        return GDK_FILTER_REMOVE;
+    }
+    return GDK_FILTER_CONTINUE;
+}
+
+static gboolean ConsumeSpnavQueue(GIOChannel *, GIOCondition, gpointer data) {
+    WindowImplGtk *window = (WindowImplGtk *)data;
+    Glib::RefPtr<Gdk::Window> gdkWindow = window->gtkWindow.get_window();
+
+    // We don't get modifier state through the socket.
+    int x, y;
+    Gdk::ModifierType mask{};
+#if GTK_CHECK_VERSION(3, 20, 0)
+    Glib::RefPtr<Gdk::Device> device = gdkWindow->get_display()->get_default_seat()->get_pointer();
+#else
+    Glib::RefPtr<Gdk::Device> device = gdkWindow->get_display()->get_device_manager()->get_client_pointer();
+#endif
+    gdkWindow->get_device_position(device, x, y, mask);
+    bool shiftDown   = (mask & Gdk::SHIFT_MASK)   != 0;
+    bool controlDown = (mask & Gdk::CONTROL_MASK) != 0;
 
-    return GDK_FILTER_REMOVE;
+    spnav_event spnavEvent;
+    while(spnav_poll_event(&spnavEvent)) {
+        ProcessSpnavEvent(window, spnavEvent, shiftDown, controlDown);
+    }
+    return TRUE;
 }
 
 void Request3DConnexionEventsForWindow(WindowRef window) {
@@ -1092,11 +1135,26 @@ void Request3DConnexionEventsForWindow(WindowRef window) {
         std::static_pointer_cast<WindowImplGtk>(window);
 
     Glib::RefPtr<Gdk::Window> gdkWindow = windowImpl->gtkWindow.get_window();
+#if defined(GDK_WINDOWING_X11)
     if(GDK_IS_X11_DISPLAY(gdkWindow->get_display()->gobj())) {
-        gdkWindow->add_filter(GdkSpnavFilter, windowImpl.get());
-        spnav_x11_open(gdk_x11_get_default_xdisplay(),
-                       gdk_x11_window_get_xid(gdkWindow->gobj()));
+        if(spnav_x11_open(gdk_x11_get_default_xdisplay(),
+                          gdk_x11_window_get_xid(gdkWindow->gobj())) != -1) {
+            gdkWindow->add_filter(GdkSpnavFilter, windowImpl.get());
+        } else if(spnav_open() != -1) {
+            g_io_add_watch(g_io_channel_unix_new(spnav_fd()), G_IO_IN,
+                           ConsumeSpnavQueue, windowImpl.get());
+        }
+    }
+#endif
+#if defined(GDK_WINDOWING_WAYLAND)
+    if(GDK_IS_WAYLAND_DISPLAY(gdkWindow->get_display()->gobj())) {
+       if(spnav_open() != -1) {
+            g_io_add_watch(g_io_channel_unix_new(spnav_fd()), G_IO_IN,
+                           ConsumeSpnavQueue, windowImpl.get());
+        }
     }
+#endif
+
 }
 #else
 void Request3DConnexionEventsForWindow(WindowRef window) {}
@@ -1295,13 +1353,16 @@ public:
         }
     }
 
+//TODO: This is not getting called when the extension selection is changed.
     void FilterChanged() {
         std::string extension = GetExtension();
         if(extension.empty())
             return;
 
         Platform::Path path = GetFilename();
-        SetCurrentName(path.WithExtension(extension).FileName());
+        if(gtkChooser->get_action() != Gtk::FILE_CHOOSER_ACTION_OPEN) {
+            SetCurrentName(path.WithExtension(extension).FileName());
+        }
     }
 
     void FreezeChoices(SettingsRef settings, const std::string &key) override {
index b2b07a8bf6e378f6cca1e686815dd74aeee29002..67d1eb976e42c285f8724e9cb06d04cc128f05a7 100644 (file)
@@ -286,7 +286,8 @@ public:
     }
 
     void PopUp() override {
-        [NSMenu popUpContextMenu:nsMenu withEvent:[NSApp currentEvent] forView:nil];
+        NSEvent* event = [NSApp currentEvent];
+        [NSMenu popUpContextMenu:nsMenu withEvent:event forView:event.window.contentView];
     }
 
     void Clear() override {
@@ -358,18 +359,25 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
 - (void)didEdit:(NSString *)text;
 
 @property double scrollerMin;
-@property double scrollerMax;
+@property double scrollerSize;
+@property double pageSize;
+
 @end
 
 @implementation SSView
 {
     NSTrackingArea     *trackingArea;
     NSTextField        *editor;
+    double             magnificationGestureCurrentZ;
+    double             rotationGestureCurrent;
+    Point2d            trackpadPositionShift;
+    bool               inTrackpadScrollGesture;
+    Platform::Window::Kind kind;
 }
 
 @synthesize acceptsFirstResponder;
 
-- (id)initWithFrame:(NSRect)frameRect {
+- (id)initWithKind:(Platform::Window::Kind)aKind {
     NSOpenGLPixelFormatAttribute attrs[] = {
         NSOpenGLPFADoubleBuffer,
         NSOpenGLPFAColorSize, 24,
@@ -377,7 +385,7 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
         0
     };
     NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
-    if(self = [super initWithFrame:frameRect pixelFormat:pixelFormat]) {
+    if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pixelFormat:pixelFormat]) {
         self.wantsBestResolutionOpenGLSurface = YES;
         self.wantsLayer = YES;
         editor = [[NSTextField alloc] init];
@@ -387,6 +395,18 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
         editor.bezeled = NO;
         editor.target = self;
         editor.action = @selector(didEdit:);
+
+        inTrackpadScrollGesture = false;
+        kind = aKind;
+        if(kind == Platform::Window::Kind::TOPLEVEL) {
+            NSGestureRecognizer *mag = [[NSMagnificationGestureRecognizer alloc] initWithTarget:self
+                action:@selector(magnifyGesture:)];
+            [self addGestureRecognizer:mag];
+
+            NSRotationGestureRecognizer* rot = [[NSRotationGestureRecognizer alloc] initWithTarget:self
+                action:@selector(rotateGesture:)];
+            [self addGestureRecognizer:rot];
+        }
     }
     return self;
 }
@@ -427,9 +447,9 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
 - (Platform::MouseEvent)convertMouseEvent:(NSEvent *)nsEvent {
     Platform::MouseEvent event = {};
 
-    NSPoint nsPoint = [self convertPoint:nsEvent.locationInWindow fromView:self];
+    NSPoint nsPoint = [self convertPoint:nsEvent.locationInWindow fromView:nil];
     event.x = nsPoint.x;
-    event.y = self.bounds.size.height - nsPoint.y;
+    event.y = nsPoint.y;
 
     NSUInteger nsFlags = [nsEvent modifierFlags];
     if(nsFlags & NSEventModifierFlagShift)   event.shiftDown   = true;
@@ -553,14 +573,57 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
     using Platform::MouseEvent;
 
     MouseEvent event = [self convertMouseEvent:nsEvent];
+    if(nsEvent.subtype == NSEventSubtypeTabletPoint && kind == Platform::Window::Kind::TOPLEVEL) {
+        // This is how Cocoa represents 2 finger trackpad drag gestures, rather than going via
+        // NSPanGestureRecognizer which is how you might expect this to work... We complicate this
+        // further by also handling shift-two-finger-drag to mean rotate. Fortunately we're using
+        // shift in the same way as right-mouse-button MouseEvent does (to converts a pan to a
+        // rotate) so we get the rotate support for free. It's a bit ugly having to fake mouse
+        // events and track the deviation from the actual mouse cursor with trackpadPositionShift,
+        // but in lieu of an event API that allows us to request a rotate/pan with relative
+        // coordinates, it's the best we can do.
+        event.button = MouseEvent::Button::RIGHT;
+        // Make sure control (actually cmd) isn't passed through, ctrl-right-click-drag has special
+        // meaning as rotate which we don't want to inadvertently trigger.
+        event.controlDown = false;
+        if(nsEvent.scrollingDeltaX == 0 && nsEvent.scrollingDeltaY == 0) {
+            // Cocoa represents the point where the user lifts their fingers off (and any inertial
+            // scrolling has finished) by an event with scrollingDeltaX and scrollingDeltaY both 0.
+            // Sometimes you also get a zero scroll at the start of a two-finger-rotate (probably
+            // reflecting the internal implementation of that being a cancelled possible pan
+            // gesture), which is why this conditional is structured the way it is.
+            if(inTrackpadScrollGesture) {
+                event.x += trackpadPositionShift.x;
+                event.y += trackpadPositionShift.y;
+                event.type = MouseEvent::Type::RELEASE;
+                receiver->onMouseEvent(event);
+                inTrackpadScrollGesture = false;
+                trackpadPositionShift = Point2d::From(0, 0);
+            }
+            return;
+        } else if(!inTrackpadScrollGesture) {
+            inTrackpadScrollGesture = true;
+            trackpadPositionShift = Point2d::From(0, 0);
+            event.type = MouseEvent::Type::PRESS;
+            receiver->onMouseEvent(event);
+            // And drop through
+        }
+
+        trackpadPositionShift.x += nsEvent.scrollingDeltaX;
+        trackpadPositionShift.y += nsEvent.scrollingDeltaY;
+        event.type = MouseEvent::Type::MOTION;
+        event.x += trackpadPositionShift.x;
+        event.y += trackpadPositionShift.y;
+        receiver->onMouseEvent(event);
+        return;
+    }
+
     event.type = MouseEvent::Type::SCROLL_VERT;
 
     bool isPrecise = [nsEvent hasPreciseScrollingDeltas];
     event.scrollDelta = [nsEvent scrollingDeltaY] / (isPrecise ? 50 : 5);
 
-    if(receiver->onMouseEvent) {
-        receiver->onMouseEvent(event);
-    }
+    receiver->onMouseEvent(event);
 }
 
 - (void)mouseExited:(NSEvent *)nsEvent {
@@ -638,6 +701,50 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
     [super keyUp:nsEvent];
 }
 
+- (void)magnifyGesture:(NSMagnificationGestureRecognizer *)gesture {
+    // The onSixDofEvent API doesn't allow us to specify the scaling's origin, so for expediency
+    // we fake out a scrollwheel MouseEvent with a suitably-scaled scrollDelta with a bit of
+    // absolute-to-relative positioning conversion tracked using magnificationGestureCurrentZ.
+
+    if(gesture.state == NSGestureRecognizerStateBegan) {
+        magnificationGestureCurrentZ = 0.0;
+    }
+
+    // Magic number to make gesture.magnification align roughly with what scrollDelta expects
+    constexpr double kScale = 10.0;
+    double z = ((double)gesture.magnification * kScale);
+    double zdelta = z - magnificationGestureCurrentZ;
+    magnificationGestureCurrentZ = z;
+
+    using Platform::MouseEvent;
+    MouseEvent event = {};
+    event.type = MouseEvent::Type::SCROLL_VERT;
+    NSPoint nsPoint = [gesture locationInView:self];
+    event.x = nsPoint.x;
+    event.y = nsPoint.y;
+    event.scrollDelta = zdelta;
+    if(receiver->onMouseEvent) {
+        receiver->onMouseEvent(event);
+    }
+}
+
+- (void)rotateGesture:(NSRotationGestureRecognizer *)gesture {
+    if(gesture.state == NSGestureRecognizerStateBegan) {
+        rotationGestureCurrent = 0.0;
+    }
+    double rotation = gesture.rotation;
+    double rotationDelta = rotation - rotationGestureCurrent;
+    rotationGestureCurrent = rotation;
+
+    using Platform::SixDofEvent;
+    SixDofEvent event = {};
+    event.type = SixDofEvent::Type::MOTION;
+    event.rotationZ = rotationDelta;
+    if(receiver->onSixDofEvent) {
+        receiver->onSixDofEvent(event);
+    }
+}
+
 @synthesize editing;
 
 - (void)startEditing:(NSString *)text at:(NSPoint)origin withHeight:(double)fontHeight
@@ -698,11 +805,27 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) {
 }
 
 @synthesize scrollerMin;
-@synthesize scrollerMax;
+@synthesize scrollerSize;
+@synthesize pageSize;
 
 - (void)didScroll:(NSScroller *)sender {
+    double pos;
+    switch(sender.hitPart) {
+        case NSScrollerKnob:
+        case NSScrollerKnobSlot:
+            pos = receiver->GetScrollbarPosition();
+            break;
+        case NSScrollerDecrementPage:
+            pos = receiver->GetScrollbarPosition() - pageSize;
+            break;
+        case NSScrollerIncrementPage:
+            pos = receiver->GetScrollbarPosition() + pageSize;
+            break;
+        default:
+            return;
+    }
+
     if(receiver->onScrollbarAdjusted) {
-        double pos = scrollerMin + [sender doubleValue] * (scrollerMax - scrollerMin);
         receiver->onScrollbarAdjusted(pos);
     }
 }
@@ -769,7 +892,7 @@ public:
     NSString         *nsToolTip;
 
     WindowImplCocoa(Window::Kind kind, std::shared_ptr<WindowImplCocoa> parentWindow) {
-        ssView = [[SSView alloc] init];
+        ssView = [[SSView alloc] initWithKind:kind];
         ssView.translatesAutoresizingMaskIntoConstraints = NO;
         ssView.receiver = this;
 
@@ -962,21 +1085,22 @@ public:
 
     void ConfigureScrollbar(double min, double max, double pageSize) override {
         ssView.scrollerMin = min;
-        ssView.scrollerMax = max - pageSize;
-        [nsScroller setKnobProportion:(pageSize / (ssView.scrollerMax - ssView.scrollerMin))];
+        ssView.scrollerSize = max + 1 - min;
+        ssView.pageSize = pageSize;
+        nsScroller.knobProportion = pageSize / ssView.scrollerSize;
+        nsScroller.hidden = pageSize >= ssView.scrollerSize;
     }
 
     double GetScrollbarPosition() override {
+        // Platform::Window scrollbar positions are in the range [min, max+1 - pageSize] inclusive,
+        // and Cocoa scrollbars are from 0.0 to 1.0 inclusive, so we have to apply some scaling and
+        // transforming. (scrollerSize is max+1-min, see ConfigureScrollbar above)
         return ssView.scrollerMin +
-            [nsScroller doubleValue] * (ssView.scrollerMax - ssView.scrollerMin);
+            nsScroller.doubleValue * (ssView.scrollerSize - ssView.pageSize);
     }
 
     void SetScrollbarPosition(double pos) override {
-        if(pos > ssView.scrollerMax)
-            pos = ssView.scrollerMax;
-        if(GetScrollbarPosition() == pos)
-            return;
-        [nsScroller setDoubleValue:(pos / (ssView.scrollerMax - ssView.scrollerMin))];
+        nsScroller.doubleValue = (pos - ssView.scrollerMin) / ( ssView.scrollerSize - ssView.pageSize);
     }
 
     void Invalidate() override {
@@ -1426,9 +1550,22 @@ void OpenInBrowser(const std::string &url) {
 - (IBAction)preferences:(id)sender;
 - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
+
+@property BOOL exiting;
+
 @end
 
 @implementation SSApplicationDelegate
+
+@synthesize exiting;
+
+- (id)init {
+    if (self = [super init]) {
+        self.exiting = false;
+    }
+    return self;
+}
+
 - (IBAction)preferences:(id)sender {
     if (!SS.GW.showTextWindow) {
         SolveSpace::SS.GW.MenuView(SolveSpace::Command::SHOW_TEXT_WND);
@@ -1443,12 +1580,27 @@ void OpenInBrowser(const std::string &url) {
 }
 
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
-    [[[NSApp mainWindow] delegate] windowShouldClose:[NSApp mainWindow]];
-    return NSTerminateCancel;
+    if(!SS.unsaved) {
+        return NSTerminateNow;
+    } else {
+        [self performSelectorOnMainThread:@selector(applicationTerminatePrompt) withObject:nil
+            waitUntilDone:NO modes:@[NSDefaultRunLoopMode, NSModalPanelRunLoopMode]];
+        return NSTerminateLater;
+    }
+}
+
+- (void)applicationWillTerminate:(NSNotification *)notification {
+    if(!exiting) {
+        // Prevent the Platform::ExitGui() call from SolveSpaceUI::Exit()
+        // triggering another terminate
+        exiting = true;
+        // Now let SS save settings etc
+        SS.Exit();
+    }
 }
 
 - (void)applicationTerminatePrompt {
-    SolveSpace::SS.MenuFile(SolveSpace::Command::EXIT);
+    [NSApp replyToApplicationShouldTerminate:SS.OkayToStartNewFile()];
 }
 @end
 
@@ -1469,6 +1621,14 @@ std::vector<std::string> InitGui(int argc, char **argv) {
     ssDelegate = [[SSApplicationDelegate alloc] init];
     NSApplication.sharedApplication.delegate = ssDelegate;
 
+    // Setting this prevents "Show Tab Bar" and "Show All Tabs" items from being
+    // automagically added to the View menu
+    NSWindow.allowsAutomaticWindowTabbing = NO;
+
+    // And this prevents the duplicate "Enter Full Screen" menu item, see
+    // https://stackoverflow.com/questions/52154977/how-to-get-rid-of-enter-full-screen-menu-item
+    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
+
     [NSBundle.mainBundle loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
 
     NSArray *languages = NSLocale.preferredLanguages;
@@ -1487,8 +1647,10 @@ void RunGui() {
 }
 
 void ExitGui() {
-    [NSApp setDelegate:nil];
-    [NSApp terminate:nil];
+    if(!ssDelegate.exiting) {
+        ssDelegate.exiting = true;
+        [NSApp terminate:nil];
+    }
 }
 
 void ClearGui() {}
index d885195896907715c6a887375f4f2d2729081831..ba9e18cf6e14962655d8c23e780f835db569b044 100644 (file)
@@ -142,7 +142,18 @@ static std::string NegateMnemonics(const std::string &label) {
     return newLabel;
 }
 
-static int Clamp(int x, int a, int b) {
+static int Clamp(int x, int a, int b, int brda, int brdb) {
+    // If we are outside of an edge of the monitor
+    // and a "border" is requested "move in" from that edge
+    // by "b/brdX" (the "b" parameter is the resolution)
+    if((x <= a) && (brda)) {
+        a += b / brda;  // yes "b/brda" since b is the size
+    }
+
+    if(((x >= b) && brdb)) {
+        b -= b / brdb;
+    }
+
     return max(a, min(x, b));
 }
 
@@ -1084,7 +1095,7 @@ public:
                         return 0;
                     }
                 } else if(wParam == VK_ESCAPE) {
-                    sscheck(SendMessageW(hWindow, msg, wParam, lParam));
+                    window->HideEditor();
                     return 0;
                 }
         }
@@ -1218,11 +1229,14 @@ public:
         sscheck(GetMonitorInfo(MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST), &mi));
 
         // If it somehow ended up off-screen, then put it back.
+        // and make it visible by at least this portion of the screen
+        const LONG movein = 40;
+
         RECT mrc = mi.rcMonitor;
-        rc.left   = Clamp(rc.left,   mrc.left, mrc.right);
-        rc.right  = Clamp(rc.right,  mrc.left, mrc.right);
-        rc.top    = Clamp(rc.top,    mrc.top,  mrc.bottom);
-        rc.bottom = Clamp(rc.bottom, mrc.top,  mrc.bottom);
+        rc.left   = Clamp(rc.left,   mrc.left, mrc.right, 0, movein);
+        rc.right  = Clamp(rc.right,  mrc.left, mrc.right, movein, 0);
+        rc.top    = Clamp(rc.top,    mrc.top,  mrc.bottom, 0, movein);
+        rc.bottom = Clamp(rc.bottom, mrc.top,  mrc.bottom, movein, 0);
 
         // And make sure the minimum size is respected. (We can freeze a size smaller
         // than minimum size if the DPI changed between runs.)
@@ -1569,11 +1583,6 @@ public:
         ofn.nMaxFile    = sizeof(filenameWC) / sizeof(wchar_t);
         ofn.Flags       = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
                           OFN_OVERWRITEPROMPT;
-        if(isSaveDialog) {
-            SetTitle(C_("title", "Save File"));
-        } else {
-            SetTitle(C_("title", "Open File"));
-        }
     }
 
     void SetTitle(std::string title) override {
@@ -1626,13 +1635,14 @@ public:
     }
 
     bool RunModal() override {
-        if(GetFilename().IsEmpty()) {
-            SetFilename(Path::From(_("untitled")));
-        }
-
         if(isSaveDialog) {
+            SetTitle(C_("title", "Save File"));
+            if(GetFilename().IsEmpty()) {
+                SetFilename(Path::From(_("untitled")));
+            }
             return GetSaveFileNameW(&ofn) == TRUE;
         } else {
+            SetTitle(C_("title", "Open File"));
             return GetOpenFileNameW(&ofn) == TRUE;
         }
     }
index 21c2b2bfac9484bd94b8e36582598bb1af0bfec3..1ad5e17580ac1f1b0ff23c914b78fb6b1564e882 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef SOLVESPACE_PLATFORM_H
 #define SOLVESPACE_PLATFORM_H
 
+namespace SolveSpace {
 namespace Platform {
 
 // UTF-8 ⟷ UTF-16 conversion, for Windows.
@@ -80,6 +81,7 @@ void DebugPrint(const char *fmt, ...);
 void *AllocTemporary(size_t size);
 void FreeAllTemporary();
 
-}
+} // namespace Platform
+} // namespace SolveSpace
 
 #endif
index 710e795d60c1cda9c05415000e98ad99119b8e49..fd948e805891edd951e1c2097a7e1c1763e112cc 100644 (file)
@@ -190,11 +190,11 @@ void SurfaceRenderer::DrawFaces(const SMesh &m, const std::vector<uint32_t> &fac
 void SurfaceRenderer::DrawPixmap(std::shared_ptr<const Pixmap> pm,
                     const Vector &o, const Vector &u, const Vector &v,
                     const Point2d &ta, const Point2d &tb, hFill hcf) {
-    ssassert(false, "Not implemented");
+    dbp("Not implemented");
 }
 
 void SurfaceRenderer::InvalidatePixmap(std::shared_ptr<const Pixmap> pm) {
-    ssassert(false, "Not implemented");
+    dbp("Not implemented");
 }
 
 //-----------------------------------------------------------------------------
index 7b19081e1d00cc1b678fe77faf31c4d074d79bb4..d3fa4caab909674fd0b415699a2e95d1f98d9e7b 100644 (file)
@@ -179,7 +179,8 @@ void Pixmap::ConvertTo(Format newFormat) {
 
 static std::shared_ptr<Pixmap> ReadPngIntoPixmap(png_struct *png_ptr, png_info *info_ptr,
                                                  bool flip) {
-    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL);
+    png_read_png(png_ptr, info_ptr,
+                 PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_SCALE_16, NULL);
 
     std::shared_ptr<Pixmap> pixmap = std::make_shared<Pixmap>();
     pixmap->width    = png_get_image_width(png_ptr, info_ptr);
@@ -564,7 +565,7 @@ const BitmapFont::Glyph &BitmapFont::GetGlyph(char32_t codepoint) {
     // Find the hex representation in the (sorted) Unifont file.
     auto first = unifontData.cbegin(),
          last  = unifontData.cend();
-    while(first <= last) {
+    while(first < last) {
         auto mid = first + (last - first) / 2;
         while(mid != unifontData.cbegin()) {
             if(*mid == '\n') {
@@ -588,7 +589,10 @@ const BitmapFont::Glyph &BitmapFont::GetGlyph(char32_t codepoint) {
         if(foundCodepoint < codepoint) {
             first = mid + 1;
             while(first != unifontData.cend()) {
-                if(*first == '\n') break;
+                if(*first == '\n') {
+                    first++;
+                    break;
+                }
                 first++;
             }
             continue; // and last stays the same
index 18c1e58217226fcaffda3a1992b689eb1bf896e1..d5c2e3f06bc04aeda4f8cd4b502f5b61fd8f1c1c 100644 (file)
@@ -7,11 +7,23 @@
 #ifndef SOLVESPACE_RESOURCE_H
 #define SOLVESPACE_RESOURCE_H
 
+#include <functional>
+#include <map>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+namespace SolveSpace {
+
 class Camera;
 class Point2d;
 class Pixmap;
 class Vector;
 class RgbaColor;
+namespace Platform {
+    class Path;
+} // namespace Platform
 
 std::string LoadString(const std::string &name);
 std::string LoadStringFromGzip(const std::string &name);
@@ -109,4 +121,5 @@ public:
                const std::function<void(Vector, Vector)> &traceEdge, const Camera &camera);
 };
 
+}
 #endif
index 83773749de3b0560ee084d5a219e5f3a19f6606a..33853d96d16112ab9ed4e9b01c7bcb88a10b2d53 100644 (file)
@@ -175,6 +175,7 @@ public:
     bool        suppress;
     bool        relaxConstraints;
     bool        allowRedundant;
+    bool        suppressDofCalculation;
     bool        allDimsReference;
     double      scale;
 
@@ -198,6 +199,9 @@ public:
         // For drawings in 2d
         WORKPLANE_BY_POINT_ORTHO   = 6000,
         WORKPLANE_BY_LINE_SEGMENTS = 6001,
+        WORKPLANE_BY_POINT_NORMAL  = 6002,
+        //WORKPLANE_BY_POINT_FACE    = 6003,
+        //WORKPLANE_BY_FACE          = 6004,
         // For extrudes, translates, and rotates
         ONE_SIDED                  = 7000,
         TWO_SIDED                  = 7001
@@ -266,6 +270,7 @@ public:
     void Generate(EntityList *entity, ParamList *param);
     bool IsSolvedOkay();
     void TransformImportedBy(Vector t, Quaternion q);
+    bool IsTriangleMeshAssembly() const;
     bool IsForcedToMeshBySource() const;
     bool IsForcedToMesh() const;
     // When a request generates entities from entities, and the source
@@ -323,6 +328,7 @@ public:
     void DrawPolyError(Canvas *canvas);
     void DrawFilledPaths(Canvas *canvas);
     void DrawContourAreaLabels(Canvas *canvas);
+    bool ShouldDrawExploded() const;
 
     SPolygon GetPolygon();
 
@@ -368,6 +374,7 @@ public:
     std::string font;
     Platform::Path file;
     double      aspectRatio;
+    int groupRequestIndex;
 
     static hParam AddParam(ParamList *param, hParam hp);
     void Generate(EntityList *entity, ParamList *param);
@@ -591,6 +598,10 @@ public:
         beziers.l.Clear();
         edges.l.Clear();
     }
+
+    bool ShouldDrawExploded() const;
+    Vector ExplodeOffset() const;
+    Vector PointGetDrawNum() const;
 };
 
 class EntReqTable {
@@ -612,7 +623,7 @@ public:
     bool        free;
 
     // Used only in the solver
-    hParam      substd;
+    Param       *substd;
 
     static const hParam NO_PARAM;
 
@@ -673,7 +684,10 @@ public:
         CURVE_CURVE_TANGENT    = 125,
         EQUAL_RADIUS           = 130,
         WHERE_DRAGGED          = 200,
-
+        ARC_ARC_LEN_RATIO      = 210,
+        ARC_LINE_LEN_RATIO     = 211,
+        ARC_ARC_DIFFERENCE     = 212,
+        ARC_LINE_DIFFERENCE    = 213,
         COMMENT                = 1000
     };
 
@@ -757,7 +771,7 @@ public:
                       Vector p0, Vector p1, Vector pt, double salient);
     void DoArcForAngle(Canvas *canvas, Canvas::hStroke hcs,
                        Vector a0, Vector da, Vector b0, Vector db,
-                       Vector offset, Vector *ref, bool trim);
+                       Vector offset, Vector *ref, bool trim, Vector explodeOffset);
     void DoArrow(Canvas *canvas, Canvas::hStroke hcs,
                  Vector p, Vector dir, Vector n, double width, double angle, double da);
     void DoLineWithArrows(Canvas *canvas, Canvas::hStroke hcs,
@@ -779,6 +793,8 @@ public:
 
     std::string DescriptionString() const;
 
+    bool ShouldDrawExploded() const;
+
     static hConstraint AddConstraint(Constraint *c, bool rememberForUndo = true);
     static void MenuConstrain(Command id);
     static void DeleteAllConstraintsFor(Constraint::Type type, hEntity entityA, hEntity ptA);
@@ -790,9 +806,9 @@ public:
     static hConstraint TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB,
                                     hEntity entityA, hEntity entityB = Entity::NO_ENTITY,
                                     bool other = false, bool other2 = false);
-    static void ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc);
-    static void ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic);
-    static void ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB);
+    static bool ConstrainArcLineTangent(Constraint *c, Entity *line, Entity *arc);
+    static bool ConstrainCubicLineTangent(Constraint *c, Entity *line, Entity *cubic);
+    static bool ConstrainCurveCurveTangent(Constraint *c, Entity *eA, Entity *eB);
 };
 
 class hEquation {
@@ -883,13 +899,18 @@ public:
         RgbaColor   color;
         double      width;
         int         zIndex;
+        bool        exportable;
+        StipplePattern stippleType;
     } Default;
     static const Default Defaults[];
 
     static std::string CnfColor(const std::string &prefix);
     static std::string CnfWidth(const std::string &prefix);
+    static std::string CnfStippleType(const std::string &prefix);
+    static std::string CnfStippleScale(const std::string &prefix);
     static std::string CnfTextHeight(const std::string &prefix);
     static std::string CnfPrefixToName(const std::string &prefix);
+    static std::string CnfExportable(const std::string &prefix);
 
     static void CreateAllDefaultStyles();
     static void CreateDefaultStyle(hStyle h);
@@ -916,7 +937,11 @@ public:
     static bool Exportable(int hs);
     static hStyle ForEntity(hEntity he);
     static StipplePattern PatternType(hStyle hs);
+    static double StippleScale(hStyle hs);
     static double StippleScaleMm(hStyle hs);
+    static std::string StipplePatternName(hStyle hs);
+    static std::string StipplePatternName(StipplePattern stippleType);
+    static StipplePattern StipplePatternFromString(std::string name);
 
     std::string DescriptionString() const;
 
index 4e458cf481beb2a0e368b2ea78804055c165b50b..a8d1a151e813ebd7c1a9dd7815117f590df92c45 100644 (file)
@@ -19,6 +19,7 @@ void SolveSpaceUI::Init() {
     Platform::SettingsRef settings = Platform::GetSettings();
 
     SS.tangentArcRadius = 10.0;
+    SS.explodeDistance = 1.0;
 
     // Then, load the registry settings.
     // Default list of colors for the model material
@@ -104,6 +105,7 @@ void SolveSpaceUI::Init() {
     exportCanvas.dy     = settings->ThawFloat("ExportCanvas_Dy",     5.0);
     // Extra parameters when exporting G code
     gCode.depth         = settings->ThawFloat("GCode_Depth", 10.0);
+    gCode.safeHeight    = settings->ThawFloat("GCode_SafeHeight", 5.0);
     gCode.passes        = settings->ThawInt("GCode_Passes", 1);
     gCode.feed          = settings->ThawFloat("GCode_Feed", 10.0);
     gCode.plungeFeed    = settings->ThawFloat("GCode_PlungeFeed", 10.0);
@@ -315,6 +317,7 @@ void SolveSpaceUI::ScheduleAutosave() {
 double SolveSpaceUI::MmPerUnit() {
     switch(viewUnits) {
         case Unit::INCHES: return 25.4;
+        case Unit::FEET_INCHES: return 25.4; // The 'unit' is still inches
         case Unit::METERS: return 1000.0;
         case Unit::MM: return 1.0;
     }
@@ -323,14 +326,47 @@ double SolveSpaceUI::MmPerUnit() {
 const char *SolveSpaceUI::UnitName() {
     switch(viewUnits) {
         case Unit::INCHES: return "in";
+        case Unit::FEET_INCHES: return "in";
         case Unit::METERS: return "m";
         case Unit::MM: return "mm";
     }
     return "";
 }
 
-std::string SolveSpaceUI::MmToString(double v) {
+std::string SolveSpaceUI::MmToString(double v, bool editable) {
     v /= MmPerUnit();
+    // The syntax 2' 6" for feet and inches is not something we can (currently)
+    // parse back from a string so if editable is true, we treat FEET_INCHES the
+    // same as INCHES and just return the unadorned decimal number of inches.
+    if(viewUnits == Unit::FEET_INCHES && !editable) {
+        // Now convert v from inches to 64'ths of an inch, to make rounding easier.
+        v = floor((v + (1.0 / 128.0)) * 64.0);
+        int feet = (int)(v / (12.0 * 64.0));
+        v = v - (feet * 12.0 * 64.0);
+        // v is now the feet-less remainder in 1/64 inches
+        int inches = (int)(v / 64.0);
+        int numerator = (int)(v - ((double)inches * 64.0));
+        int denominator = 64;
+        // Divide down to smallest denominator where the numerator is still a whole number
+        while ((numerator != 0) && ((numerator & 1) == 0)) {
+            numerator /= 2;
+            denominator /= 2;
+        }
+        std::ostringstream str;
+        if(feet != 0) {
+            str << feet << "'-";
+        }
+        // For something like 0.5, show 1/2" rather than 0 1/2"
+        if(!(feet == 0 && inches == 0 && numerator != 0)) {
+            str << inches;
+        }
+        if(numerator != 0) {
+            str << " " << numerator << "/" << denominator;
+        }
+        str << "\"";
+        return str.str();
+    }
+
     int digits = UnitDigitsAfterDecimal();
     double minimum = 0.5 * pow(10,-digits);
     while ((v < minimum) && (v > LENGTH_EPS)) {
@@ -349,7 +385,7 @@ static const char *DimToString(int dim) {
 }
 static std::pair<int, std::string> SelectSIPrefixMm(int ord, int dim) {
 // decide what units to use depending on the order of magnitude of the
-// measure in meters and the dimmension (1,2,3 lenear, area, volume)
+// measure in meters and the dimension (1,2,3 lenear, area, volume)
     switch(dim) {
         case 0:
         case 1:
@@ -378,7 +414,7 @@ static std::pair<int, std::string> SelectSIPrefixMm(int ord, int dim) {
         default:
             dbp ("dimensions over 3 not supported");
             break;
-    }        
+    }
     return {0, "m"};
 }
 static std::pair<int, std::string> SelectSIPrefixInch(int deg) {
@@ -394,17 +430,22 @@ std::string SolveSpaceUI::MmToStringSI(double v, int dim) {
         dim = 1;
     }
 
-    v /= pow((viewUnits == Unit::INCHES) ? 25.4 : 1000, dim);
+    bool inches = (viewUnits == Unit::INCHES) || (viewUnits == Unit::FEET_INCHES);
+    v /= pow(inches ? 25.4 : 1000, dim);
     int vdeg = (int)(log10(fabs(v)));
     std::string unit;
     if(fabs(v) > 0.0) {
         int sdeg = 0;
         std::tie(sdeg, unit) =
-            (viewUnits == Unit::INCHES)
+            inches
             ? SelectSIPrefixInch(vdeg/dim)
             : SelectSIPrefixMm(vdeg, dim);
         v /= pow(10.0, sdeg * dim);
     }
+    if(viewUnits == Unit::FEET_INCHES && fabs(v) > pow(12.0, dim)) {
+        unit = "ft";
+        v /= pow(12.0, dim);
+    }
     int pdeg = (int)ceil(log10(fabs(v) + 1e-10));
     return ssprintf("%.*g%s%s%s", pdeg + UnitDigitsAfterDecimal(), v,
                     compact ? "" : " ", unit.c_str(), DimToString(dim));
@@ -434,10 +475,11 @@ int SolveSpaceUI::GetMaxSegments() {
     return maxSegments;
 }
 int SolveSpaceUI::UnitDigitsAfterDecimal() {
-    return (viewUnits == Unit::INCHES) ? afterDecimalInch : afterDecimalMm;
+    return (viewUnits == Unit::INCHES || viewUnits == Unit::FEET_INCHES) ?
+           afterDecimalInch : afterDecimalMm;
 }
 void SolveSpaceUI::SetUnitDigitsAfterDecimal(int v) {
-    if(viewUnits == Unit::INCHES) {
+    if(viewUnits == Unit::INCHES || viewUnits == Unit::FEET_INCHES) {
         afterDecimalInch = v;
     } else {
         afterDecimalMm = v;
@@ -764,7 +806,11 @@ void SolveSpaceUI::MenuAnalyze(Command id) {
                     SS.TW.stepDim.isDistance =
                         (c->type != Constraint::Type::ANGLE) &&
                         (c->type != Constraint::Type::LENGTH_RATIO) &&
-                        (c->type != Constraint::Type::LENGTH_DIFFERENCE);
+                        (c->type != Constraint::Type::ARC_ARC_LEN_RATIO) &&
+                        (c->type != Constraint::Type::ARC_LINE_LEN_RATIO) &&
+                        (c->type != Constraint::Type::LENGTH_DIFFERENCE) &&
+                        (c->type != Constraint::Type::ARC_ARC_DIFFERENCE) &&
+                        (c->type != Constraint::Type::ARC_LINE_DIFFERENCE) ;
                     SS.TW.shown.constraint = c->h;
                     SS.TW.shown.screen = TextWindow::Screen::STEP_DIMENSION;
 
@@ -1007,7 +1053,11 @@ void SolveSpaceUI::MenuHelp(Command id) {
 "law. For details, visit http://gnu.org/licenses/\n"
 "\n"
 "© 2008-%d Jonathan Westhues and other authors.\n"),
-PACKAGE_VERSION, 2021);
+PACKAGE_VERSION, 2022);
+            break;
+
+        case Command::GITHUB:
+            Platform::OpenInBrowser(GIT_HASH_URL);
             break;
 
         default: ssassert(false, "Unexpected menu ID");
@@ -1026,12 +1076,14 @@ void SolveSpaceUI::Clear() {
     GW.showGridMenuItem = NULL;
     GW.dimSolidModelMenuItem = NULL;
     GW.perspectiveProjMenuItem = NULL;
+    GW.explodeMenuItem = NULL;
     GW.showToolbarMenuItem = NULL;
     GW.showTextWndMenuItem = NULL;
     GW.fullScreenMenuItem = NULL;
     GW.unitsMmMenuItem = NULL;
     GW.unitsMetersMenuItem = NULL;
     GW.unitsInchesMenuItem = NULL;
+    GW.unitsFeetInchesMenuItem = NULL;
     GW.inWorkplaneMenuItem = NULL;
     GW.in3dMenuItem = NULL;
     GW.undoMenuItem = NULL;
index e64a1ab864a484748667fc62f08d5ab68e5115bc..1c22db62904f026653dd3a2afa49d1c07be0d7ad 100644 (file)
@@ -7,6 +7,10 @@
 #ifndef SOLVESPACE_H
 #define SOLVESPACE_H
 
+#include "resource.h"
+#include "platform/platform.h"
+#include "platform/gui.h"
+
 #include <cctype>
 #include <climits>
 #include <cmath>
 #include <unordered_set>
 #include <vector>
 
+#define EIGEN_NO_DEBUG
+#undef Success
+#include <Eigen/SparseCore>
+
 // We declare these in advance instead of simply using FT_Library
 // (defined as typedef FT_LibraryRec_* FT_Library) because including
 // freetype.h invokes indescribable horrors and we would like to avoid
@@ -122,9 +130,6 @@ static constexpr double LENGTH_EPS    =  1e-6;
 static constexpr double VERY_POSITIVE =  1e10;
 static constexpr double VERY_NEGATIVE = -1e10;
 
-#include "platform/platform.h"
-#include "platform/gui.h"
-#include "resource.h"
 
 using Platform::AllocTemporary;
 using Platform::FreeAllTemporary;
@@ -138,7 +143,8 @@ enum class Command : uint32_t;
 enum class Unit : uint32_t {
     MM = 0,
     INCHES,
-    METERS
+    METERS,
+    FEET_INCHES
 };
 
 template<class Key, class T>
@@ -209,7 +215,7 @@ void Error(const char *fmt, ...);
 
 class System {
 public:
-    enum { MAX_UNKNOWNS = 1024 };
+    enum { MAX_UNKNOWNS = 2048 };
 
     EntityList                      entity;
     ParamList                       param;
@@ -231,37 +237,34 @@ public:
     // The system Jacobian matrix
     struct {
         // The corresponding equation for each row
-        hEquation   eq[MAX_UNKNOWNS];
+        std::vector<Equation *> eq;
 
         // The corresponding parameter for each column
-        hParam      param[MAX_UNKNOWNS];
+        std::vector<hParam>     param;
 
         // We're solving AX = B
         int m, n;
         struct {
-            Expr        *sym[MAX_UNKNOWNS][MAX_UNKNOWNS];
-            double       num[MAX_UNKNOWNS][MAX_UNKNOWNS];
-        }           A;
-
-        double      scale[MAX_UNKNOWNS];
-
-        // Some helpers for the least squares solve
-        double AAt[MAX_UNKNOWNS][MAX_UNKNOWNS];
-        double Z[MAX_UNKNOWNS];
+            // This only observes the Expr - does not own them!
+            Eigen::SparseMatrix<Expr *> sym;
+            Eigen::SparseMatrix<double> num;
+        } A;
 
-        double      X[MAX_UNKNOWNS];
+        Eigen::VectorXd scale;
+        Eigen::VectorXd X;
 
         struct {
-            Expr        *sym[MAX_UNKNOWNS];
-            double       num[MAX_UNKNOWNS];
-        }           B;
+            // This only observes the Expr - does not own them!
+            std::vector<Expr *> sym;
+            Eigen::VectorXd     num;
+        } B;
     } mat;
 
-    static const double RANK_MAG_TOLERANCE, CONVERGE_TOLERANCE;
+    static const double CONVERGE_TOLERANCE;
     int CalculateRank();
-    bool TestRank(int *rank = NULL);
-    static bool SolveLinearSystem(double X[], double A[][MAX_UNKNOWNS],
-                                  double B[], int N);
+    bool TestRank(int *dof = NULL);
+    static bool SolveLinearSystem(const Eigen::SparseMatrix<double> &A,
+                                  const Eigen::VectorXd &B, Eigen::VectorXd *X);
     bool SolveLeastSquares();
 
     bool WriteJacobian(int tag);
@@ -277,7 +280,6 @@ public:
     bool NewtonSolve(int tag);
 
     void MarkParamsFree(bool findFree);
-    int CalculateDof();
 
     SolveResult Solve(Group *g, int *rank = NULL, int *dof = NULL,
                       List<hConstraint> *bad = NULL,
@@ -289,6 +291,9 @@ public:
                           bool andFindBad = false, bool andFindFree = false);
 
     void Clear();
+    Param *GetLastParamSubstitution(Param *p);
+    void SubstituteParamsByLast(Expr *e);
+    void SortSubstitutionByDragged(Param *p);
 };
 
 #include "ttf.h"
@@ -597,6 +602,7 @@ public:
     }        exportCanvas;
     struct {
         double  depth;
+        double  safeHeight;
         int     passes;
         double  feed;
         double  plungeFeed;
@@ -608,8 +614,10 @@ public:
     int      afterDecimalDegree;
     bool     useSIPrefixes;
     int      autosaveInterval; // in minutes
+    bool     explode;
+    double   explodeDistance;
 
-    std::string MmToString(double v);
+    std::string MmToString(double v, bool editable=false);
     std::string MmToStringSI(double v, int dim = 0);
     std::string DegreeToString(double v);
     double ExprToMm(Expr *e);
@@ -812,6 +820,7 @@ public:
 void ImportDxf(const Platform::Path &file);
 void ImportDwg(const Platform::Path &file);
 bool LinkIDF(const Platform::Path &filename, EntityList *le, SMesh *m, SShell *sh);
+bool LinkStl(const Platform::Path &filename, EntityList *le, SMesh *m, SShell *sh);
 
 extern SolveSpaceUI SS;
 extern Sketch SK;
index 1edf46ed5df39dd7c784795c6b76f4b82f599697..7700e1b654cf9b8028a2ee5fd55bd8e3305586db 100644 (file)
@@ -29,7 +29,7 @@ void SCurve::GetAxisAlignedBounding(Vector *ptMax, Vector *ptMin) const {
     }
 }
 
-// We will be inserting other curve verticies into our curves to split them.
+// We will be inserting other curve vertices into our curves to split them.
 // This is helpful when curved surfaces become tangent along a trim and the
 // usual tests for curve-surface intersection don't split the curve at a vertex.
 // This is faster than the previous version that split at surface corners and
@@ -521,20 +521,19 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
     SEdgeList inter = {};
 
     SSurface *ss;
-    SCurve *sc;
-    for(sc = into->curve.First(); sc; sc = into->curve.NextAfter(sc)) {
-        if(sc->source != SCurve::Source::INTERSECTION) continue;
+    for(SCurve &sc : into->curve) {
+        if(sc.source != SCurve::Source::INTERSECTION) continue;
         if(opA) {
-            if(sc->surfA != h) continue;
-            ss = shb->surface.FindById(sc->surfB);
+            if(sc.surfA != h) continue;
+            ss = shb->surface.FindById(sc.surfB);
         } else {
-            if(sc->surfB != h) continue;
-            ss = sha->surface.FindById(sc->surfA);
+            if(sc.surfB != h) continue;
+            ss = sha->surface.FindById(sc.surfA);
         }
         int i;
-        for(i = 1; i < sc->pts.n; i++) {
-            Vector a = sc->pts[i-1].p,
-                   b = sc->pts[i].p;
+        for(i = 1; i < sc.pts.n; i++) {
+            Vector a = sc.pts[i-1].p,
+                   b = sc.pts[i].p;
 
             Point2d auv, buv;
             ss->ClosestPointTo(a, &(auv.x), &(auv.y));
@@ -560,9 +559,9 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
                     bkwds = !bkwds;
                 }
                 if(bkwds) {
-                    inter.AddEdge(tb, ta, sc->h.v, 1);
+                    inter.AddEdge(tb, ta, sc.h.v, 1);
                 } else {
-                    inter.AddEdge(ta, tb, sc->h.v, 0);
+                    inter.AddEdge(ta, tb, sc.h.v, 0);
                 }
             }
         }
@@ -711,20 +710,18 @@ void SShell::MakeIntersectionCurvesAgainst(SShell *agnst, SShell *into) {
     for(int i = 0; i< surface.n; i++) {
         SSurface *sa = &surface[i];
 
-        SSurface *sb;
-        for(sb = agnst->surface.First(); sb; sb = agnst->surface.NextAfter(sb)){
+        for(SSurface &sb : agnst->surface){
             // Intersect every surface from our shell against every surface
             // from agnst; this will add zero or more curves to the curve
             // list for into.
-            sa->IntersectAgainst(sb, this, agnst, into);
+            sa->IntersectAgainst(&sb, this, agnst, into);
         }
     }
 }
 
 void SShell::CleanupAfterBoolean() {
-    SSurface *ss;
-    for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
-        ss->edges.Clear();
+    for(SSurface &ss : surface) {
+        ss.edges.Clear();
     }
 }
 
@@ -734,10 +731,9 @@ void SShell::CleanupAfterBoolean() {
 // by their new IDs.
 //-----------------------------------------------------------------------------
 void SShell::RewriteSurfaceHandlesForCurves(SShell *a, SShell *b) {
-    SCurve *sc;
-    for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
-        sc->surfA = sc->GetSurfaceA(a, b)->newH,
-        sc->surfB = sc->GetSurfaceB(a, b)->newH;
+    for(SCurve &sc : curve) {
+        sc.surfA = sc.GetSurfaceA(a, b)->newH,
+        sc.surfB = sc.GetSurfaceB(a, b)->newH;
     }
 }
 
@@ -759,32 +755,32 @@ void SShell::MakeFromAssemblyOf(SShell *a, SShell *b) {
     // First, copy over all the curves. Note which shell (a or b) each curve
     // came from, but assign it a new ID.
     curve.ReserveMore(a->curve.n + b->curve.n);
-    SCurve *c, cn;
+    SCurve cn;
     for(i = 0; i < 2; i++) {
         ab = (i == 0) ? a : b;
-        for(c = ab->curve.First(); c; c = ab->curve.NextAfter(c)) {
-            cn = SCurve::FromTransformationOf(c, t, q, 1.0);
+        for(SCurve &c : ab->curve) {
+            cn = SCurve::FromTransformationOf(&c, t, q, 1.0);
             cn.source = (i == 0) ? SCurve::Source::A : SCurve::Source::B;
             // surfA and surfB are wrong now, and we can't fix them until
             // we've assigned IDs to the surfaces. So we'll get that later.
-            c->newH = curve.AddAndAssignId(&cn);
+            c.newH = curve.AddAndAssignId(&cn);
         }
     }
 
     // Likewise copy over all the surfaces.
     surface.ReserveMore(a->surface.n + b->surface.n);
-    SSurface *s, sn;
+    SSurface sn;
     for(i = 0; i < 2; i++) {
         ab = (i == 0) ? a : b;
-        for(s = ab->surface.First(); s; s = ab->surface.NextAfter(s)) {
-            sn = SSurface::FromTransformationOf(s, t, q, 1.0, /*includingTrims=*/true);
+        for(SSurface &s : ab->surface) {
+            sn = SSurface::FromTransformationOf(&s, t, q, 1.0, /*includingTrims=*/true);
             // All the trim curve IDs get rewritten; we know the new handles
             // to the curves since we recorded them in the previous step.
             STrimBy *stb;
             for(stb = sn.trim.First(); stb; stb = sn.trim.NextAfter(stb)) {
                 stb->curve = ab->curve.FindById(stb->curve)->newH;
             }
-            s->newH = surface.AddAndAssignId(&sn);
+            s.newH = surface.AddAndAssignId(&sn);
         }
     }
 
@@ -800,7 +796,7 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, SSurface::CombineAs type) {
     b->MakeClassifyingBsps(NULL);
 
     // Copy over all the original curves, splitting them so that a
-    // piecwise linear segment never crosses a surface from the other
+    // piecewise linear segment never crosses a surface from the other
     // shell.
     a->CopyCurvesSplitAgainst(/*opA=*/true,  b, this);
     b->CopyCurvesSplitAgainst(/*opA=*/false, a, this);
@@ -809,12 +805,11 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, SSurface::CombineAs type) {
     // the surfaces in B (which is all of the intersection curves).
     a->MakeIntersectionCurvesAgainst(b, this);
 
-    SCurve *sc;
-    for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
-        SSurface *srfA = sc->GetSurfaceA(a, b),
-                       *srfB = sc->GetSurfaceB(a, b);
+    for(SCurve &sc : curve) {
+        SSurface *srfA = sc.GetSurfaceA(a, b),
+                 *srfB = sc.GetSurfaceB(a, b);
 
-        sc->RemoveShortSegments(srfA, srfB);
+        sc.RemoveShortSegments(srfA, srfB);
     }
 
     // And clean up the piecewise linear things we made as a calculation aid
index 55496b67080e51663d8671b150f6dfc3a1f900cd..382415b17c986dde8866c2ed2738a9fecdd9d8d4 100644 (file)
@@ -817,7 +817,7 @@ void SCurve::RemoveShortSegments(SSurface *srfA, SSurface *srfB) {
             continue;
         }
 
-        // if the curve is exact and points are >0.05 appart wrt t, point is there
+        // if the curve is exact and points are >0.05 apart wrt t, point is there
         // deliberately regardless of chord tolerance (ex: small circles)
         tprev = t = tnext = 0;
         if (isExact) {
index a91a307fa895efc1bf2b99c5ae771970c2735eb0..42ae5590678163a6979774242d5bb544b0b70c0c 100644 (file)
@@ -58,10 +58,9 @@ void SShell::MergeCoincidentSurfaces() {
 
                 // All the references to this surface get replaced with the
                 // new srf
-                SCurve *sc;
-                for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
-                    if(sc->surfA == sj->h) sc->surfA = si->h;
-                    if(sc->surfB == sj->h) sc->surfB = si->h;
+                for(SCurve &sc : curve) {
+                    if(sc.surfA == sj->h) sc.surfA = si->h;
+                    if(sc.surfB == sj->h) sc.surfB = si->h;
                 }
             }
 
index 587792821a060090d3f527e7e44f99ee3d437680..f1c0d2bd6c15d98a762dcdee685874b30413681a 100644 (file)
@@ -381,9 +381,8 @@ void SShell::AllPointsIntersecting(Vector a, Vector b,
                                    List<SInter> *il,
                                    bool asSegment, bool trimmed, bool inclTangent)
 {
-    SSurface *ss;
-    for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
-        ss->AllPointsIntersecting(a, b, il,
+    for(SSurface &ss : surface) {
+        ss.AllPointsIntersecting(a, b, il,
             asSegment, trimmed, inclTangent);
     }
 }
@@ -434,11 +433,10 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
     // First, check for edge-on-edge
     int edge_inters = 0;
     Vector inter_surf_n[2], inter_edge_n[2];
-    SSurface *srf;
-    for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
-        if(srf->LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
+    for(SSurface &srf : surface) {
+        if(srf.LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
 
-        SEdgeList *sel = &(srf->edges);
+        SEdgeList *sel = &(srf.edges);
         SEdge *se;
         for(se = sel->l.First(); se; se = sel->l.NextAfter(se)) {
             if((ea.Equals(se->a) && eb.Equals(se->b)) ||
@@ -448,9 +446,9 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
                 if(edge_inters < 2) {
                     // Edge-on-edge case
                     Point2d pm;
-                    srf->ClosestPointTo(p,  &pm, /*mustConverge=*/false);
+                    srf.ClosestPointTo(p,  &pm, /*mustConverge=*/false);
                     // A vector normal to the surface, at the intersection point
-                    inter_surf_n[edge_inters] = srf->NormalAt(pm);
+                    inter_surf_n[edge_inters] = srf.NormalAt(pm);
                     // A vector normal to the intersecting edge (but within the
                     // intersecting surface) at the intersection point, pointing
                     // out.
@@ -520,25 +518,25 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
     // are on surface) and for numerical stability, so we don't pick up
     // the additional error from the line intersection.
 
-    for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
-        if(srf->LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
+    for(SSurface &srf : surface) {
+        if(srf.LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
 
         Point2d puv;
-        srf->ClosestPointTo(p, &(puv.x), &(puv.y), /*mustConverge=*/false);
-        Vector pp = srf->PointAt(puv);
+        srf.ClosestPointTo(p, &(puv.x), &(puv.y), /*mustConverge=*/false);
+        Vector pp = srf.PointAt(puv);
 
         if((pp.Minus(p)).Magnitude() > LENGTH_EPS) continue;
         Point2d dummy = { 0, 0 };
-        SBspUv::Class c = (srf->bsp) ? srf->bsp->ClassifyPoint(puv, dummy, srf) : SBspUv::Class::OUTSIDE;
+        SBspUv::Class c = (srf.bsp) ? srf.bsp->ClassifyPoint(puv, dummy, &srf) : SBspUv::Class::OUTSIDE;
         if(c == SBspUv::Class::OUTSIDE) continue;
 
         // Edge-on-face (unless edge-on-edge above superceded)
         Point2d pin, pout;
-        srf->ClosestPointTo(p.Plus(edge_n_in),  &pin,  /*mustConverge=*/false);
-        srf->ClosestPointTo(p.Plus(edge_n_out), &pout, /*mustConverge=*/false);
+        srf.ClosestPointTo(p.Plus(edge_n_in),  &pin,  /*mustConverge=*/false);
+        srf.ClosestPointTo(p.Plus(edge_n_out), &pout, /*mustConverge=*/false);
 
-        Vector surf_n_in  = srf->NormalAt(pin),
-               surf_n_out = srf->NormalAt(pout);
+        Vector surf_n_in  = srf.NormalAt(pin),
+               surf_n_out = srf.NormalAt(pout);
 
         *indir  = ClassifyRegion(edge_n_in,  surf_n_in,  surf_n);
         *outdir = ClassifyRegion(edge_n_out, surf_n_out, surf_n);
diff --git a/src/srf/shell.cpp b/src/srf/shell.cpp
new file mode 100644 (file)
index 0000000..ca3b75e
--- /dev/null
@@ -0,0 +1,614 @@
+//-----------------------------------------------------------------------------
+// Anything involving NURBS shells (i.e., shells); except
+// for the real math, which is in ratpoly.cpp.
+//
+// Copyright 2008-2013 Jonathan Westhues.
+//-----------------------------------------------------------------------------
+#include "../solvespace.h"
+
+typedef struct {
+    hSCurve     hc;
+    hSSurface   hs;
+} TrimLine;
+
+
+void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, RgbaColor color)
+{
+    // Make the extrusion direction consistent with respect to the normal
+    // of the sketch we're extruding.
+    if((t0.Minus(t1)).Dot(sbls->normal) < 0) {
+        swap(t0, t1);
+    }
+
+    // Define a coordinate system to contain the original sketch, and get
+    // a bounding box in that csys
+    Vector n = sbls->normal.ScaledBy(-1);
+    Vector u = n.Normal(0), v = n.Normal(1);
+    Vector orig = sbls->point;
+    double umax = VERY_NEGATIVE, umin = VERY_POSITIVE;
+    sbls->GetBoundingProjd(u, orig, &umin, &umax);
+    double vmax = VERY_NEGATIVE, vmin = VERY_POSITIVE;
+    sbls->GetBoundingProjd(v, orig, &vmin, &vmax);
+    // and now fix things up so that all u and v lie between 0 and 1
+    orig = orig.Plus(u.ScaledBy(umin));
+    orig = orig.Plus(v.ScaledBy(vmin));
+    u = u.ScaledBy(umax - umin);
+    v = v.ScaledBy(vmax - vmin);
+
+    // So we can now generate the top and bottom surfaces of the extrusion,
+    // planes within a translated (and maybe mirrored) version of that csys.
+    SSurface s0, s1;
+    s0 = SSurface::FromPlane(orig.Plus(t0), u, v);
+    s0.color = color;
+    s1 = SSurface::FromPlane(orig.Plus(t1).Plus(u), u.ScaledBy(-1), v);
+    s1.color = color;
+    hSSurface hs0 = surface.AddAndAssignId(&s0),
+              hs1 = surface.AddAndAssignId(&s1);
+
+    // Now go through the input curves. For each one, generate its surface
+    // of extrusion, its two translated trim curves, and one trim line. We
+    // go through by loops so that we can assign the lines correctly.
+    SBezierLoop *sbl;
+    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+        SBezier *sb;
+        List<TrimLine> trimLines = {};
+
+        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
+            // Generate the surface of extrusion of this curve, and add
+            // it to the list
+            SSurface ss = SSurface::FromExtrusionOf(sb, t0, t1);
+            ss.color = color;
+            hSSurface hsext = surface.AddAndAssignId(&ss);
+
+            // Translate the curve by t0 and t1 to produce two trim curves
+            SCurve sc = {};
+            sc.isExact = true;
+            sc.exact = sb->TransformedBy(t0, Quaternion::IDENTITY, 1.0);
+            (sc.exact).MakePwlInto(&(sc.pts));
+            sc.surfA = hs0;
+            sc.surfB = hsext;
+            hSCurve hc0 = curve.AddAndAssignId(&sc);
+
+            sc = {};
+            sc.isExact = true;
+            sc.exact = sb->TransformedBy(t1, Quaternion::IDENTITY, 1.0);
+            (sc.exact).MakePwlInto(&(sc.pts));
+            sc.surfA = hs1;
+            sc.surfB = hsext;
+            hSCurve hc1 = curve.AddAndAssignId(&sc);
+
+            STrimBy stb0, stb1;
+            // The translated curves trim the flat top and bottom surfaces.
+            stb0 = STrimBy::EntireCurve(this, hc0, /*backwards=*/false);
+            stb1 = STrimBy::EntireCurve(this, hc1, /*backwards=*/true);
+            (surface.FindById(hs0))->trim.Add(&stb0);
+            (surface.FindById(hs1))->trim.Add(&stb1);
+
+            // The translated curves also trim the surface of extrusion.
+            stb0 = STrimBy::EntireCurve(this, hc0, /*backwards=*/true);
+            stb1 = STrimBy::EntireCurve(this, hc1, /*backwards=*/false);
+            (surface.FindById(hsext))->trim.Add(&stb0);
+            (surface.FindById(hsext))->trim.Add(&stb1);
+
+            // And form the trim line
+            Vector pt = sb->Finish();
+            sc = {};
+            sc.isExact = true;
+            sc.exact = SBezier::From(pt.Plus(t0), pt.Plus(t1));
+            (sc.exact).MakePwlInto(&(sc.pts));
+            hSCurve hl = curve.AddAndAssignId(&sc);
+            // save this for later
+            TrimLine tl;
+            tl.hc = hl;
+            tl.hs = hsext;
+            trimLines.Add(&tl);
+        }
+
+        int i;
+        for(i = 0; i < trimLines.n; i++) {
+            TrimLine *tl = &(trimLines[i]);
+            SSurface *ss = surface.FindById(tl->hs);
+
+            TrimLine *tlp = &(trimLines[WRAP(i-1, trimLines.n)]);
+
+            STrimBy stb;
+            stb = STrimBy::EntireCurve(this, tl->hc, /*backwards=*/true);
+            ss->trim.Add(&stb);
+            stb = STrimBy::EntireCurve(this, tlp->hc, /*backwards=*/false);
+            ss->trim.Add(&stb);
+
+            (curve.FindById(tl->hc))->surfA = ss->h;
+            (curve.FindById(tlp->hc))->surfB = ss->h;
+        }
+        trimLines.Clear();
+    }
+}
+
+bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis, double da, double dx)
+// Check that the direction of revolution/extrusion ends up parallel to the normal of
+// the sketch, on the side of the axis where the sketch is.
+{
+    SBezierLoop *sbl;
+    Vector pto;
+    double md = VERY_NEGATIVE;
+    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+        SBezier *sb;
+        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
+            // Choose the point farthest from the axis; we'll get garbage
+            // if we choose a point that lies on the axis, for example.
+            // (And our surface will be self-intersecting if the sketch
+            // spans the axis, so don't worry about that.)
+            for(int i = 0; i <= sb->deg; i++) {
+                Vector p = sb->ctrl[i];
+                double d = p.DistanceToLine(pt, axis);
+                if(d > md) {
+                    md  = d;
+                    pto = p;
+                }
+            }
+        }
+    }
+    Vector ptc = pto.ClosestPointOnLine(pt, axis),
+           up = axis.Cross(pto.Minus(ptc)).ScaledBy(da),
+           vp = up.Plus(axis.ScaledBy(dx));
+   
+    return (vp.Dot(sbls->normal) > 0);
+}
+
+// sketch must not contain the axis of revolution as a non-construction line for helix
+void SShell::MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
+                                         RgbaColor color, Group *group, double angles,
+                                         double anglef, double dists, double distf) {
+    int i0 = surface.n; // number of pre-existing surfaces
+    SBezierLoop *sbl;
+    // for testing - hard code the axial distance, and number of sections.
+    // distance will need to be parameters in the future.
+    double dist  = distf - dists;
+    int sections = (int)(fabs(anglef - angles) / (PI / 2) + 1);
+    double wedge = (anglef - angles) / sections;
+    int startMapping = Group::REMAP_LATHE_START, endMapping = Group::REMAP_LATHE_END;
+
+    if(CheckNormalAxisRelationship(sbls, pt, axis, anglef-angles, distf-dists)) {
+        swap(angles, anglef);
+        swap(dists, distf);
+        dist  = -dist;
+        wedge = -wedge;
+        swap(startMapping, endMapping);
+    }
+
+    // Define a coordinate system to contain the original sketch, and get
+    // a bounding box in that csys
+    Vector n = sbls->normal.ScaledBy(-1);
+    Vector u = n.Normal(0), v = n.Normal(1);
+    Vector orig = sbls->point;
+    double umax = VERY_NEGATIVE, umin = VERY_POSITIVE;
+    sbls->GetBoundingProjd(u, orig, &umin, &umax);
+    double vmax = VERY_NEGATIVE, vmin = VERY_POSITIVE;
+    sbls->GetBoundingProjd(v, orig, &vmin, &vmax);
+    // and now fix things up so that all u and v lie between 0 and 1
+    orig = orig.Plus(u.ScaledBy(umin));
+    orig = orig.Plus(v.ScaledBy(vmin));
+    u    = u.ScaledBy(umax - umin);
+    v    = v.ScaledBy(vmax - vmin);
+
+    // So we can now generate the end caps of the extrusion within
+    // a translated and rotated (and maybe mirrored) version of that csys.
+    SSurface s0, s1;
+    s0 = SSurface::FromPlane(orig.RotatedAbout(pt, axis, angles).Plus(axis.ScaledBy(dists)),
+                             u.RotatedAbout(axis, angles), v.RotatedAbout(axis, angles));
+    s0.color = color;
+
+    hEntity face0 = group->Remap(Entity::NO_ENTITY, startMapping);
+    s0.face = face0.v;
+
+    s1 = SSurface::FromPlane(
+        orig.Plus(u).RotatedAbout(pt, axis, anglef).Plus(axis.ScaledBy(distf)),
+        u.ScaledBy(-1).RotatedAbout(axis, anglef), v.RotatedAbout(axis, anglef));
+    s1.color = color;
+
+    hEntity face1 = group->Remap(Entity::NO_ENTITY, endMapping);
+    s1.face = face1.v;
+
+    hSSurface hs0 = surface.AddAndAssignId(&s0);
+    hSSurface hs1 = surface.AddAndAssignId(&s1);
+
+    // Now we actually build and trim the swept surfaces. One loop at a time.
+    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+        int i, j;
+        SBezier *sb;
+        List<std::vector<hSSurface>> hsl = {};
+
+        // This is where all the NURBS are created and Remapped to the generating curve
+        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
+            std::vector<hSSurface> revs(sections);
+            for(j = 0; j < sections; j++) {
+                if((dist == 0) && sb->deg == 1 &&
+                   (sb->ctrl[0]).DistanceToLine(pt, axis) < LENGTH_EPS &&
+                   (sb->ctrl[1]).DistanceToLine(pt, axis) < LENGTH_EPS) {
+                    // This is a line on the axis of revolution; it does
+                    // not contribute a surface.
+                    revs[j].v = 0;
+                } else {
+                    SSurface ss = SSurface::FromRevolutionOf(
+                        sb, pt, axis, angles + (wedge)*j, angles + (wedge) * (j + 1),
+                        dists + j * dist / sections, dists + (j + 1) * dist / sections);
+                    ss.color = color;
+                    if(sb->entity != 0) {
+                        hEntity he;
+                        he.v          = sb->entity;
+                        hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
+                        if(SK.entity.FindByIdNoOops(hface) != NULL) {
+                            ss.face = hface.v;
+                        }
+                    }
+                    revs[j] = surface.AddAndAssignId(&ss);
+                }
+            }
+            hsl.Add(&revs);
+        }
+        // Still the same loop. Need to create trim curves
+        for(i = 0; i < sbl->l.n; i++) {
+            std::vector<hSSurface> revs = hsl[i], revsp = hsl[WRAP(i - 1, sbl->l.n)];
+
+            sb = &(sbl->l[i]);
+
+            // we will need the grid t-values for this entire row of surfaces
+            List<double> t_values;
+            t_values = {};
+            if (revs[0].v) { 
+                double ps = 0.0;
+                t_values.Add(&ps);
+                (surface.FindById(revs[0]))->MakeTriangulationGridInto(
+                        &t_values, 0.0, 1.0, true, 0);
+            }
+            // we generate one more curve than we did surfaces
+            for(j = 0; j <= sections; j++) {
+                SCurve sc;
+                Quaternion qs = Quaternion::From(axis, angles + wedge * j);
+                // we want Q*(x - p) + p = Q*x + (p - Q*p)
+                Vector ts =
+                    pt.Minus(qs.Rotate(pt)).Plus(axis.ScaledBy(dists + j * dist / sections));
+
+                // If this input curve generated a surface, then trim that
+                // surface with the rotated version of the input curve.
+                if(revs[0].v) { // not d[j] because crash on j==sections
+                    sc         = {};
+                    sc.isExact = true;
+                    sc.exact   = sb->TransformedBy(ts, qs, 1.0);
+                    // make the PWL for the curve based on t value list
+                    for(int x = 0; x < t_values.n; x++) {
+                        SCurvePt scpt;
+                        scpt.tag    = 0;
+                        scpt.p      = sc.exact.PointAt(t_values[x]);
+                        scpt.vertex = (x == 0) || (x == (t_values.n - 1));
+                        sc.pts.Add(&scpt);
+                    }
+
+                    // the surfaces already exists so trim with this curve
+                    if(j < sections) {
+                        sc.surfA = revs[j];
+                    } else {
+                        sc.surfA = hs1; // end cap
+                    }
+
+                    if(j > 0) {
+                        sc.surfB = revs[j - 1];
+                    } else {
+                        sc.surfB = hs0; // staring cap
+                    }
+
+                    hSCurve hcb = curve.AddAndAssignId(&sc);
+
+                    STrimBy stb;
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
+                    (surface.FindById(sc.surfA))->trim.Add(&stb);
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
+                    (surface.FindById(sc.surfB))->trim.Add(&stb);
+                } else if(j == 0) { // curve was on the rotation axis and is shared by the end caps.
+                    sc         = {};
+                    sc.isExact = true;
+                    sc.exact   = sb->TransformedBy(ts, qs, 1.0);
+                    (sc.exact).MakePwlInto(&(sc.pts));
+                    sc.surfA    = hs1; // end cap
+                    sc.surfB    = hs0; // staring cap
+                    hSCurve hcb = curve.AddAndAssignId(&sc);
+
+                    STrimBy stb;
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
+                    (surface.FindById(sc.surfA))->trim.Add(&stb);
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
+                    (surface.FindById(sc.surfB))->trim.Add(&stb);
+                }
+
+                // And if this input curve and the one after it both generated
+                // surfaces, then trim both of those by the appropriate
+                // curve based on the control points.
+                if((j < sections) && revs[j].v && revsp[j].v) {
+                    SSurface *ss = surface.FindById(revs[j]);
+
+                    sc         = {};
+                    sc.isExact = true;
+                    sc.exact   = SBezier::From(ss->ctrl[0][0], ss->ctrl[0][1], ss->ctrl[0][2]);
+                    sc.exact.weight[1] = ss->weight[0][1];
+                    double max_dt = 0.5;
+                    if (sc.exact.deg > 1) max_dt = 0.125;
+                    (sc.exact).MakePwlInto(&(sc.pts), 0.0, max_dt);
+                    sc.surfA = revs[j];
+                    sc.surfB = revsp[j];
+
+                    hSCurve hcc = curve.AddAndAssignId(&sc);
+
+                    STrimBy stb;
+                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/false);
+                    (surface.FindById(sc.surfA))->trim.Add(&stb);
+                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/true);
+                    (surface.FindById(sc.surfB))->trim.Add(&stb);
+                }
+            }
+            t_values.Clear();
+        }
+
+        hsl.Clear();
+    }
+
+    if(dist == 0) {
+        MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
+    }
+}
+
+void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color,
+                                  Group *group) {
+    int i0 = surface.n; // number of pre-existing surfaces
+    SBezierLoop *sbl;
+
+    if(CheckNormalAxisRelationship(sbls, pt, axis, 1.0, 0.0)) {
+        axis = axis.ScaledBy(-1);
+    }
+
+    // Now we actually build and trim the surfaces.
+    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
+        int i, j;
+        SBezier *sb;
+        List<std::vector<hSSurface>> hsl = {};
+
+        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
+            std::vector<hSSurface> revs(4);
+            for(j = 0; j < 4; j++) {
+                if(sb->deg == 1 &&
+                    (sb->ctrl[0]).DistanceToLine(pt, axis) < LENGTH_EPS &&
+                    (sb->ctrl[1]).DistanceToLine(pt, axis) < LENGTH_EPS)
+                {
+                    // This is a line on the axis of revolution; it does
+                    // not contribute a surface.
+                    revs[j].v = 0;
+                } else {
+                    SSurface ss = SSurface::FromRevolutionOf(sb, pt, axis, (PI / 2) * j,
+                                                             (PI / 2) * (j + 1), 0.0, 0.0);
+                    ss.color = color;
+                    if(sb->entity != 0) {
+                        hEntity he;
+                        he.v = sb->entity;
+                        hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
+                        if(SK.entity.FindByIdNoOops(hface) != NULL) {
+                            ss.face = hface.v;
+                        }
+                    }
+                    revs[j] = surface.AddAndAssignId(&ss);
+                }
+            }
+            hsl.Add(&revs);
+        }
+
+        for(i = 0; i < sbl->l.n; i++) {
+            std::vector<hSSurface> revs  = hsl[i],
+                     revsp = hsl[WRAP(i-1, sbl->l.n)];
+
+            sb   = &(sbl->l[i]);
+
+            for(j = 0; j < 4; j++) {
+                SCurve sc;
+                Quaternion qs = Quaternion::From(axis, (PI/2)*j);
+                // we want Q*(x - p) + p = Q*x + (p - Q*p)
+                Vector ts = pt.Minus(qs.Rotate(pt));
+
+                // If this input curve generate a surface, then trim that
+                // surface with the rotated version of the input curve.
+                if(revs[j].v) {
+                    sc = {};
+                    sc.isExact = true;
+                    sc.exact = sb->TransformedBy(ts, qs, 1.0);
+                    (sc.exact).MakePwlInto(&(sc.pts));
+                    sc.surfA = revs[j];
+                    sc.surfB = revs[WRAP(j-1, 4)];
+
+                    hSCurve hcb = curve.AddAndAssignId(&sc);
+
+                    STrimBy stb;
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
+                    (surface.FindById(sc.surfA))->trim.Add(&stb);
+                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
+                    (surface.FindById(sc.surfB))->trim.Add(&stb);
+                }
+
+                // And if this input curve and the one after it both generated
+                // surfaces, then trim both of those by the appropriate
+                // circle.
+                if(revs[j].v && revsp[j].v) {
+                    SSurface *ss = surface.FindById(revs[j]);
+
+                    sc = {};
+                    sc.isExact = true;
+                    sc.exact = SBezier::From(ss->ctrl[0][0],
+                                             ss->ctrl[0][1],
+                                             ss->ctrl[0][2]);
+                    sc.exact.weight[1] = ss->weight[0][1];
+                    (sc.exact).MakePwlInto(&(sc.pts));
+                    sc.surfA = revs[j];
+                    sc.surfB = revsp[j];
+
+                    hSCurve hcc = curve.AddAndAssignId(&sc);
+
+                    STrimBy stb;
+                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/false);
+                    (surface.FindById(sc.surfA))->trim.Add(&stb);
+                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/true);
+                    (surface.FindById(sc.surfB))->trim.Add(&stb);
+                }
+            }
+        }
+
+        hsl.Clear();
+    }
+
+    MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
+}
+
+void SShell::MakeFirstOrderRevolvedSurfaces(Vector pt, Vector axis, int i0) {
+    int i;
+
+    for(i = i0; i < surface.n; i++) {
+        SSurface *srf = &(surface[i]);
+
+        // Revolution of a line; this is potentially a plane, which we can
+        // rewrite to have degree (1, 1).
+        if(srf->degm == 1 && srf->degn == 2) {
+            // close start, far start, far finish
+            Vector cs, fs, ff;
+            double d0, d1;
+            d0 = (srf->ctrl[0][0]).DistanceToLine(pt, axis);
+            d1 = (srf->ctrl[1][0]).DistanceToLine(pt, axis);
+
+            if(d0 > d1) {
+                cs = srf->ctrl[1][0];
+                fs = srf->ctrl[0][0];
+                ff = srf->ctrl[0][2];
+            } else {
+                cs = srf->ctrl[0][0];
+                fs = srf->ctrl[1][0];
+                ff = srf->ctrl[1][2];
+            }
+
+            // origin close, origin far
+            Vector oc = cs.ClosestPointOnLine(pt, axis),
+                   of = fs.ClosestPointOnLine(pt, axis);
+
+            if(oc.Equals(of)) {
+                // This is a plane, not a (non-degenerate) cone.
+                Vector oldn = srf->NormalAt(0.5, 0.5);
+
+                Vector u = fs.Minus(of), v;
+
+                v = (axis.Cross(u)).WithMagnitude(1);
+
+                double vm = (ff.Minus(of)).Dot(v);
+                v = v.ScaledBy(vm);
+
+                srf->degm = 1;
+                srf->degn = 1;
+                srf->ctrl[0][0] = of;
+                srf->ctrl[0][1] = of.Plus(u);
+                srf->ctrl[1][0] = of.Plus(v);
+                srf->ctrl[1][1] = of.Plus(u).Plus(v);
+                srf->weight[0][0] = 1;
+                srf->weight[0][1] = 1;
+                srf->weight[1][0] = 1;
+                srf->weight[1][1] = 1;
+
+                if(oldn.Dot(srf->NormalAt(0.5, 0.5)) < 0) {
+                    swap(srf->ctrl[0][0], srf->ctrl[1][0]);
+                    swap(srf->ctrl[0][1], srf->ctrl[1][1]);
+                }
+                continue;
+            }
+
+            if(fabs(d0 - d1) < LENGTH_EPS) {
+                // This is a cylinder; so transpose it so that we'll recognize
+                // it as a surface of extrusion.
+                SSurface sn = *srf;
+
+                // Transposing u and v flips the normal, so reverse u to
+                // flip it again and put it back where we started.
+                sn.degm = 2;
+                sn.degn = 1;
+                int dm, dn;
+                for(dm = 0; dm <= 1; dm++) {
+                    for(dn = 0; dn <= 2; dn++) {
+                        sn.ctrl  [dn][dm] = srf->ctrl  [1-dm][dn];
+                        sn.weight[dn][dm] = srf->weight[1-dm][dn];
+                    }
+                }
+
+                *srf = sn;
+                continue;
+            }
+        }
+    }
+}
+
+void SShell::MakeFromCopyOf(SShell *a) {
+    ssassert(this != a, "Can't make from copy of self");
+    MakeFromTransformationOf(a,
+        Vector::From(0, 0, 0), Quaternion::IDENTITY, 1.0);
+}
+
+void SShell::MakeFromTransformationOf(SShell *a,
+                                      Vector t, Quaternion q, double scale)
+{
+    booleanFailed = false;
+    surface.ReserveMore(a->surface.n);
+    for(SSurface &s : a->surface) {
+        SSurface n;
+        n = SSurface::FromTransformationOf(&s, t, q, scale, /*includingTrims=*/true);
+        surface.Add(&n); // keeping the old ID
+    }
+
+    curve.ReserveMore(a->curve.n);
+    for(SCurve &c : a->curve) {
+        SCurve n;
+        n = SCurve::FromTransformationOf(&c, t, q, scale);
+        curve.Add(&n); // keeping the old ID
+    }
+}
+
+void SShell::MakeEdgesInto(SEdgeList *sel) {
+    for(SSurface &s : surface) {
+        s.MakeEdgesInto(this, sel, SSurface::MakeAs::XYZ);
+    }
+}
+
+void SShell::MakeSectionEdgesInto(Vector n, double d, SEdgeList *sel, SBezierList *sbl)
+{
+    for(SSurface &s : surface) {
+        if(s.CoincidentWithPlane(n, d)) {
+            s.MakeSectionEdgesInto(this, sel, sbl);
+        }
+    }
+}
+
+void SShell::TriangulateInto(SMesh *sm) {
+#pragma omp parallel for
+    for(int i=0; i<surface.n; i++) {
+        SSurface *s = &surface[i];
+        SMesh m;
+        s->TriangulateInto(this, &m);
+        #pragma omp critical
+        sm->MakeFromCopyOf(&m);
+        m.Clear();
+    }
+}
+
+bool SShell::IsEmpty() const {
+    return surface.IsEmpty();
+}
+
+void SShell::Clear() {
+    for(SSurface &s : surface) {
+        s.Clear();
+    }
+    surface.Clear();
+
+    for(SCurve &c : curve) {
+        c.Clear();
+    }
+    curve.Clear();
+}
index 815aedad23749e6b19b1c09dfe2a2484277ffdda..18edabf61796747a73bf70a41ef0c2fe125b3a22 100644 (file)
@@ -489,614 +489,4 @@ void SSurface::Clear() {
     trim.Clear();
 }
 
-typedef struct {
-    hSCurve     hc;
-    hSSurface   hs;
-} TrimLine;
 
-void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, RgbaColor color)
-{
-    // Make the extrusion direction consistent with respect to the normal
-    // of the sketch we're extruding.
-    if((t0.Minus(t1)).Dot(sbls->normal) < 0) {
-        swap(t0, t1);
-    }
-
-    // Define a coordinate system to contain the original sketch, and get
-    // a bounding box in that csys
-    Vector n = sbls->normal.ScaledBy(-1);
-    Vector u = n.Normal(0), v = n.Normal(1);
-    Vector orig = sbls->point;
-    double umax = VERY_NEGATIVE, umin = VERY_POSITIVE;
-    sbls->GetBoundingProjd(u, orig, &umin, &umax);
-    double vmax = VERY_NEGATIVE, vmin = VERY_POSITIVE;
-    sbls->GetBoundingProjd(v, orig, &vmin, &vmax);
-    // and now fix things up so that all u and v lie between 0 and 1
-    orig = orig.Plus(u.ScaledBy(umin));
-    orig = orig.Plus(v.ScaledBy(vmin));
-    u = u.ScaledBy(umax - umin);
-    v = v.ScaledBy(vmax - vmin);
-
-    // So we can now generate the top and bottom surfaces of the extrusion,
-    // planes within a translated (and maybe mirrored) version of that csys.
-    SSurface s0, s1;
-    s0 = SSurface::FromPlane(orig.Plus(t0), u, v);
-    s0.color = color;
-    s1 = SSurface::FromPlane(orig.Plus(t1).Plus(u), u.ScaledBy(-1), v);
-    s1.color = color;
-    hSSurface hs0 = surface.AddAndAssignId(&s0),
-              hs1 = surface.AddAndAssignId(&s1);
-
-    // Now go through the input curves. For each one, generate its surface
-    // of extrusion, its two translated trim curves, and one trim line. We
-    // go through by loops so that we can assign the lines correctly.
-    SBezierLoop *sbl;
-    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
-        SBezier *sb;
-        List<TrimLine> trimLines = {};
-
-        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
-            // Generate the surface of extrusion of this curve, and add
-            // it to the list
-            SSurface ss = SSurface::FromExtrusionOf(sb, t0, t1);
-            ss.color = color;
-            hSSurface hsext = surface.AddAndAssignId(&ss);
-
-            // Translate the curve by t0 and t1 to produce two trim curves
-            SCurve sc = {};
-            sc.isExact = true;
-            sc.exact = sb->TransformedBy(t0, Quaternion::IDENTITY, 1.0);
-            (sc.exact).MakePwlInto(&(sc.pts));
-            sc.surfA = hs0;
-            sc.surfB = hsext;
-            hSCurve hc0 = curve.AddAndAssignId(&sc);
-
-            sc = {};
-            sc.isExact = true;
-            sc.exact = sb->TransformedBy(t1, Quaternion::IDENTITY, 1.0);
-            (sc.exact).MakePwlInto(&(sc.pts));
-            sc.surfA = hs1;
-            sc.surfB = hsext;
-            hSCurve hc1 = curve.AddAndAssignId(&sc);
-
-            STrimBy stb0, stb1;
-            // The translated curves trim the flat top and bottom surfaces.
-            stb0 = STrimBy::EntireCurve(this, hc0, /*backwards=*/false);
-            stb1 = STrimBy::EntireCurve(this, hc1, /*backwards=*/true);
-            (surface.FindById(hs0))->trim.Add(&stb0);
-            (surface.FindById(hs1))->trim.Add(&stb1);
-
-            // The translated curves also trim the surface of extrusion.
-            stb0 = STrimBy::EntireCurve(this, hc0, /*backwards=*/true);
-            stb1 = STrimBy::EntireCurve(this, hc1, /*backwards=*/false);
-            (surface.FindById(hsext))->trim.Add(&stb0);
-            (surface.FindById(hsext))->trim.Add(&stb1);
-
-            // And form the trim line
-            Vector pt = sb->Finish();
-            sc = {};
-            sc.isExact = true;
-            sc.exact = SBezier::From(pt.Plus(t0), pt.Plus(t1));
-            (sc.exact).MakePwlInto(&(sc.pts));
-            hSCurve hl = curve.AddAndAssignId(&sc);
-            // save this for later
-            TrimLine tl;
-            tl.hc = hl;
-            tl.hs = hsext;
-            trimLines.Add(&tl);
-        }
-
-        int i;
-        for(i = 0; i < trimLines.n; i++) {
-            TrimLine *tl = &(trimLines[i]);
-            SSurface *ss = surface.FindById(tl->hs);
-
-            TrimLine *tlp = &(trimLines[WRAP(i-1, trimLines.n)]);
-
-            STrimBy stb;
-            stb = STrimBy::EntireCurve(this, tl->hc, /*backwards=*/true);
-            ss->trim.Add(&stb);
-            stb = STrimBy::EntireCurve(this, tlp->hc, /*backwards=*/false);
-            ss->trim.Add(&stb);
-
-            (curve.FindById(tl->hc))->surfA = ss->h;
-            (curve.FindById(tlp->hc))->surfB = ss->h;
-        }
-        trimLines.Clear();
-    }
-}
-
-bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis, double da, double dx)
-// Check that the direction of revolution/extrusion ends up parallel to the normal of
-// the sketch, on the side of the axis where the sketch is.
-{
-    SBezierLoop *sbl;
-    Vector pto;
-    double md = VERY_NEGATIVE;
-    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
-        SBezier *sb;
-        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
-            // Choose the point farthest from the axis; we'll get garbage
-            // if we choose a point that lies on the axis, for example.
-            // (And our surface will be self-intersecting if the sketch
-            // spans the axis, so don't worry about that.)
-            for(int i = 0; i <= sb->deg; i++) {
-                Vector p = sb->ctrl[i];
-                double d = p.DistanceToLine(pt, axis);
-                if(d > md) {
-                    md  = d;
-                    pto = p;
-                }
-            }
-        }
-    }
-    Vector ptc = pto.ClosestPointOnLine(pt, axis),
-           up = axis.Cross(pto.Minus(ptc)).ScaledBy(da),
-           vp = up.Plus(axis.ScaledBy(dx));
-   
-    return (vp.Dot(sbls->normal) > 0);
-}
-
-// sketch must not contain the axis of revolution as a non-construction line for helix
-void SShell::MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
-                                         RgbaColor color, Group *group, double angles,
-                                         double anglef, double dists, double distf) {
-    int i0 = surface.n; // number of pre-existing surfaces
-    SBezierLoop *sbl;
-    // for testing - hard code the axial distance, and number of sections.
-    // distance will need to be parameters in the future.
-    double dist  = distf - dists;
-    int sections = (int)(fabs(anglef - angles) / (PI / 2) + 1);
-    double wedge = (anglef - angles) / sections;
-    int startMapping = Group::REMAP_LATHE_START, endMapping = Group::REMAP_LATHE_END;
-
-    if(CheckNormalAxisRelationship(sbls, pt, axis, anglef-angles, distf-dists)) {
-        swap(angles, anglef);
-        swap(dists, distf);
-        dist  = -dist;
-        wedge = -wedge;
-        swap(startMapping, endMapping);
-    }
-
-    // Define a coordinate system to contain the original sketch, and get
-    // a bounding box in that csys
-    Vector n = sbls->normal.ScaledBy(-1);
-    Vector u = n.Normal(0), v = n.Normal(1);
-    Vector orig = sbls->point;
-    double umax = VERY_NEGATIVE, umin = VERY_POSITIVE;
-    sbls->GetBoundingProjd(u, orig, &umin, &umax);
-    double vmax = VERY_NEGATIVE, vmin = VERY_POSITIVE;
-    sbls->GetBoundingProjd(v, orig, &vmin, &vmax);
-    // and now fix things up so that all u and v lie between 0 and 1
-    orig = orig.Plus(u.ScaledBy(umin));
-    orig = orig.Plus(v.ScaledBy(vmin));
-    u    = u.ScaledBy(umax - umin);
-    v    = v.ScaledBy(vmax - vmin);
-
-    // So we can now generate the end caps of the extrusion within
-    // a translated and rotated (and maybe mirrored) version of that csys.
-    SSurface s0, s1;
-    s0 = SSurface::FromPlane(orig.RotatedAbout(pt, axis, angles).Plus(axis.ScaledBy(dists)),
-                             u.RotatedAbout(axis, angles), v.RotatedAbout(axis, angles));
-    s0.color = color;
-
-    hEntity face0 = group->Remap(Entity::NO_ENTITY, startMapping);
-    s0.face = face0.v;
-
-    s1 = SSurface::FromPlane(
-        orig.Plus(u).RotatedAbout(pt, axis, anglef).Plus(axis.ScaledBy(distf)),
-        u.ScaledBy(-1).RotatedAbout(axis, anglef), v.RotatedAbout(axis, anglef));
-    s1.color = color;
-
-    hEntity face1 = group->Remap(Entity::NO_ENTITY, endMapping);
-    s1.face = face1.v;
-
-    hSSurface hs0 = surface.AddAndAssignId(&s0);
-    hSSurface hs1 = surface.AddAndAssignId(&s1);
-
-    // Now we actually build and trim the swept surfaces. One loop at a time.
-    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
-        int i, j;
-        SBezier *sb;
-        List<std::vector<hSSurface>> hsl = {};
-
-        // This is where all the NURBS are created and Remapped to the generating curve
-        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
-            std::vector<hSSurface> revs(sections);
-            for(j = 0; j < sections; j++) {
-                if((dist == 0) && sb->deg == 1 &&
-                   (sb->ctrl[0]).DistanceToLine(pt, axis) < LENGTH_EPS &&
-                   (sb->ctrl[1]).DistanceToLine(pt, axis) < LENGTH_EPS) {
-                    // This is a line on the axis of revolution; it does
-                    // not contribute a surface.
-                    revs[j].v = 0;
-                } else {
-                    SSurface ss = SSurface::FromRevolutionOf(
-                        sb, pt, axis, angles + (wedge)*j, angles + (wedge) * (j + 1),
-                        dists + j * dist / sections, dists + (j + 1) * dist / sections);
-                    ss.color = color;
-                    if(sb->entity != 0) {
-                        hEntity he;
-                        he.v          = sb->entity;
-                        hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
-                        if(SK.entity.FindByIdNoOops(hface) != NULL) {
-                            ss.face = hface.v;
-                        }
-                    }
-                    revs[j] = surface.AddAndAssignId(&ss);
-                }
-            }
-            hsl.Add(&revs);
-        }
-        // Still the same loop. Need to create trim curves
-        for(i = 0; i < sbl->l.n; i++) {
-            std::vector<hSSurface> revs = hsl[i], revsp = hsl[WRAP(i - 1, sbl->l.n)];
-
-            sb = &(sbl->l[i]);
-
-            // we will need the grid t-values for this entire row of surfaces
-            List<double> t_values;
-            t_values = {};
-            if (revs[0].v) { 
-                double ps = 0.0;
-                t_values.Add(&ps);
-                (surface.FindById(revs[0]))->MakeTriangulationGridInto(
-                        &t_values, 0.0, 1.0, true, 0);
-            }
-            // we generate one more curve than we did surfaces
-            for(j = 0; j <= sections; j++) {
-                SCurve sc;
-                Quaternion qs = Quaternion::From(axis, angles + wedge * j);
-                // we want Q*(x - p) + p = Q*x + (p - Q*p)
-                Vector ts =
-                    pt.Minus(qs.Rotate(pt)).Plus(axis.ScaledBy(dists + j * dist / sections));
-
-                // If this input curve generated a surface, then trim that
-                // surface with the rotated version of the input curve.
-                if(revs[0].v) { // not d[j] because crash on j==sections
-                    sc         = {};
-                    sc.isExact = true;
-                    sc.exact   = sb->TransformedBy(ts, qs, 1.0);
-                    // make the PWL for the curve based on t value list
-                    for(int x = 0; x < t_values.n; x++) {
-                        SCurvePt scpt;
-                        scpt.tag    = 0;
-                        scpt.p      = sc.exact.PointAt(t_values[x]);
-                        scpt.vertex = (x == 0) || (x == (t_values.n - 1));
-                        sc.pts.Add(&scpt);
-                    }
-
-                    // the surfaces already exists so trim with this curve
-                    if(j < sections) {
-                        sc.surfA = revs[j];
-                    } else {
-                        sc.surfA = hs1; // end cap
-                    }
-
-                    if(j > 0) {
-                        sc.surfB = revs[j - 1];
-                    } else {
-                        sc.surfB = hs0; // staring cap
-                    }
-
-                    hSCurve hcb = curve.AddAndAssignId(&sc);
-
-                    STrimBy stb;
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
-                    (surface.FindById(sc.surfA))->trim.Add(&stb);
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
-                    (surface.FindById(sc.surfB))->trim.Add(&stb);
-                } else if(j == 0) { // curve was on the rotation axis and is shared by the end caps.
-                    sc         = {};
-                    sc.isExact = true;
-                    sc.exact   = sb->TransformedBy(ts, qs, 1.0);
-                    (sc.exact).MakePwlInto(&(sc.pts));
-                    sc.surfA    = hs1; // end cap
-                    sc.surfB    = hs0; // staring cap
-                    hSCurve hcb = curve.AddAndAssignId(&sc);
-
-                    STrimBy stb;
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
-                    (surface.FindById(sc.surfA))->trim.Add(&stb);
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
-                    (surface.FindById(sc.surfB))->trim.Add(&stb);
-                }
-
-                // And if this input curve and the one after it both generated
-                // surfaces, then trim both of those by the appropriate
-                // curve based on the control points.
-                if((j < sections) && revs[j].v && revsp[j].v) {
-                    SSurface *ss = surface.FindById(revs[j]);
-
-                    sc         = {};
-                    sc.isExact = true;
-                    sc.exact   = SBezier::From(ss->ctrl[0][0], ss->ctrl[0][1], ss->ctrl[0][2]);
-                    sc.exact.weight[1] = ss->weight[0][1];
-                    double max_dt = 0.5;
-                    if (sc.exact.deg > 1) max_dt = 0.125;
-                    (sc.exact).MakePwlInto(&(sc.pts), 0.0, max_dt);
-                    sc.surfA = revs[j];
-                    sc.surfB = revsp[j];
-
-                    hSCurve hcc = curve.AddAndAssignId(&sc);
-
-                    STrimBy stb;
-                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/false);
-                    (surface.FindById(sc.surfA))->trim.Add(&stb);
-                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/true);
-                    (surface.FindById(sc.surfB))->trim.Add(&stb);
-                }
-            }
-            t_values.Clear();
-        }
-
-        hsl.Clear();
-    }
-
-    if(dist == 0) {
-        MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
-    }
-}
-
-void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color,
-                                  Group *group) {
-    int i0 = surface.n; // number of pre-existing surfaces
-    SBezierLoop *sbl;
-
-    if(CheckNormalAxisRelationship(sbls, pt, axis, 1.0, 0.0)) {
-        axis = axis.ScaledBy(-1);
-    }
-
-    // Now we actually build and trim the surfaces.
-    for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
-        int i, j;
-        SBezier *sb;
-        List<std::vector<hSSurface>> hsl = {};
-
-        for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
-            std::vector<hSSurface> revs(4);
-            for(j = 0; j < 4; j++) {
-                if(sb->deg == 1 &&
-                    (sb->ctrl[0]).DistanceToLine(pt, axis) < LENGTH_EPS &&
-                    (sb->ctrl[1]).DistanceToLine(pt, axis) < LENGTH_EPS)
-                {
-                    // This is a line on the axis of revolution; it does
-                    // not contribute a surface.
-                    revs[j].v = 0;
-                } else {
-                    SSurface ss = SSurface::FromRevolutionOf(sb, pt, axis, (PI / 2) * j,
-                                                             (PI / 2) * (j + 1), 0.0, 0.0);
-                    ss.color = color;
-                    if(sb->entity != 0) {
-                        hEntity he;
-                        he.v = sb->entity;
-                        hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
-                        if(SK.entity.FindByIdNoOops(hface) != NULL) {
-                            ss.face = hface.v;
-                        }
-                    }
-                    revs[j] = surface.AddAndAssignId(&ss);
-                }
-            }
-            hsl.Add(&revs);
-        }
-
-        for(i = 0; i < sbl->l.n; i++) {
-            std::vector<hSSurface> revs  = hsl[i],
-                     revsp = hsl[WRAP(i-1, sbl->l.n)];
-
-            sb   = &(sbl->l[i]);
-
-            for(j = 0; j < 4; j++) {
-                SCurve sc;
-                Quaternion qs = Quaternion::From(axis, (PI/2)*j);
-                // we want Q*(x - p) + p = Q*x + (p - Q*p)
-                Vector ts = pt.Minus(qs.Rotate(pt));
-
-                // If this input curve generate a surface, then trim that
-                // surface with the rotated version of the input curve.
-                if(revs[j].v) {
-                    sc = {};
-                    sc.isExact = true;
-                    sc.exact = sb->TransformedBy(ts, qs, 1.0);
-                    (sc.exact).MakePwlInto(&(sc.pts));
-                    sc.surfA = revs[j];
-                    sc.surfB = revs[WRAP(j-1, 4)];
-
-                    hSCurve hcb = curve.AddAndAssignId(&sc);
-
-                    STrimBy stb;
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
-                    (surface.FindById(sc.surfA))->trim.Add(&stb);
-                    stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
-                    (surface.FindById(sc.surfB))->trim.Add(&stb);
-                }
-
-                // And if this input curve and the one after it both generated
-                // surfaces, then trim both of those by the appropriate
-                // circle.
-                if(revs[j].v && revsp[j].v) {
-                    SSurface *ss = surface.FindById(revs[j]);
-
-                    sc = {};
-                    sc.isExact = true;
-                    sc.exact = SBezier::From(ss->ctrl[0][0],
-                                             ss->ctrl[0][1],
-                                             ss->ctrl[0][2]);
-                    sc.exact.weight[1] = ss->weight[0][1];
-                    (sc.exact).MakePwlInto(&(sc.pts));
-                    sc.surfA = revs[j];
-                    sc.surfB = revsp[j];
-
-                    hSCurve hcc = curve.AddAndAssignId(&sc);
-
-                    STrimBy stb;
-                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/false);
-                    (surface.FindById(sc.surfA))->trim.Add(&stb);
-                    stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/true);
-                    (surface.FindById(sc.surfB))->trim.Add(&stb);
-                }
-            }
-        }
-
-        hsl.Clear();
-    }
-
-    MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
-}
-
-void SShell::MakeFirstOrderRevolvedSurfaces(Vector pt, Vector axis, int i0) {
-    int i;
-
-    for(i = i0; i < surface.n; i++) {
-        SSurface *srf = &(surface[i]);
-
-        // Revolution of a line; this is potentially a plane, which we can
-        // rewrite to have degree (1, 1).
-        if(srf->degm == 1 && srf->degn == 2) {
-            // close start, far start, far finish
-            Vector cs, fs, ff;
-            double d0, d1;
-            d0 = (srf->ctrl[0][0]).DistanceToLine(pt, axis);
-            d1 = (srf->ctrl[1][0]).DistanceToLine(pt, axis);
-
-            if(d0 > d1) {
-                cs = srf->ctrl[1][0];
-                fs = srf->ctrl[0][0];
-                ff = srf->ctrl[0][2];
-            } else {
-                cs = srf->ctrl[0][0];
-                fs = srf->ctrl[1][0];
-                ff = srf->ctrl[1][2];
-            }
-
-            // origin close, origin far
-            Vector oc = cs.ClosestPointOnLine(pt, axis),
-                   of = fs.ClosestPointOnLine(pt, axis);
-
-            if(oc.Equals(of)) {
-                // This is a plane, not a (non-degenerate) cone.
-                Vector oldn = srf->NormalAt(0.5, 0.5);
-
-                Vector u = fs.Minus(of), v;
-
-                v = (axis.Cross(u)).WithMagnitude(1);
-
-                double vm = (ff.Minus(of)).Dot(v);
-                v = v.ScaledBy(vm);
-
-                srf->degm = 1;
-                srf->degn = 1;
-                srf->ctrl[0][0] = of;
-                srf->ctrl[0][1] = of.Plus(u);
-                srf->ctrl[1][0] = of.Plus(v);
-                srf->ctrl[1][1] = of.Plus(u).Plus(v);
-                srf->weight[0][0] = 1;
-                srf->weight[0][1] = 1;
-                srf->weight[1][0] = 1;
-                srf->weight[1][1] = 1;
-
-                if(oldn.Dot(srf->NormalAt(0.5, 0.5)) < 0) {
-                    swap(srf->ctrl[0][0], srf->ctrl[1][0]);
-                    swap(srf->ctrl[0][1], srf->ctrl[1][1]);
-                }
-                continue;
-            }
-
-            if(fabs(d0 - d1) < LENGTH_EPS) {
-                // This is a cylinder; so transpose it so that we'll recognize
-                // it as a surface of extrusion.
-                SSurface sn = *srf;
-
-                // Transposing u and v flips the normal, so reverse u to
-                // flip it again and put it back where we started.
-                sn.degm = 2;
-                sn.degn = 1;
-                int dm, dn;
-                for(dm = 0; dm <= 1; dm++) {
-                    for(dn = 0; dn <= 2; dn++) {
-                        sn.ctrl  [dn][dm] = srf->ctrl  [1-dm][dn];
-                        sn.weight[dn][dm] = srf->weight[1-dm][dn];
-                    }
-                }
-
-                *srf = sn;
-                continue;
-            }
-        }
-    }
-}
-
-void SShell::MakeFromCopyOf(SShell *a) {
-    ssassert(this != a, "Can't make from copy of self");
-    MakeFromTransformationOf(a,
-        Vector::From(0, 0, 0), Quaternion::IDENTITY, 1.0);
-}
-
-void SShell::MakeFromTransformationOf(SShell *a,
-                                      Vector t, Quaternion q, double scale)
-{
-    booleanFailed = false;
-    surface.ReserveMore(a->surface.n);
-    SSurface *s;
-    for(s = a->surface.First(); s; s = a->surface.NextAfter(s)) {
-        SSurface n;
-        n = SSurface::FromTransformationOf(s, t, q, scale, /*includingTrims=*/true);
-        surface.Add(&n); // keeping the old ID
-    }
-
-    curve.ReserveMore(a->curve.n);
-    SCurve *c;
-    for(c = a->curve.First(); c; c = a->curve.NextAfter(c)) {
-        SCurve n;
-        n = SCurve::FromTransformationOf(c, t, q, scale);
-        curve.Add(&n); // keeping the old ID
-    }
-}
-
-void SShell::MakeEdgesInto(SEdgeList *sel) {
-    SSurface *s;
-    for(s = surface.First(); s; s = surface.NextAfter(s)) {
-        s->MakeEdgesInto(this, sel, SSurface::MakeAs::XYZ);
-    }
-}
-
-void SShell::MakeSectionEdgesInto(Vector n, double d, SEdgeList *sel, SBezierList *sbl)
-{
-    SSurface *s;
-    for(s = surface.First(); s; s = surface.NextAfter(s)) {
-        if(s->CoincidentWithPlane(n, d)) {
-            s->MakeSectionEdgesInto(this, sel, sbl);
-        }
-    }
-}
-
-void SShell::TriangulateInto(SMesh *sm) {
-#pragma omp parallel for
-    for(int i=0; i<surface.n; i++) {
-        SSurface *s = &surface[i];
-        SMesh m;
-        s->TriangulateInto(this, &m);
-        #pragma omp critical
-        sm->MakeFromCopyOf(&m);
-        m.Clear();
-    }
-}
-
-bool SShell::IsEmpty() const {
-    return surface.IsEmpty();
-}
-
-void SShell::Clear() {
-    SSurface *s;
-    for(s = surface.First(); s; s = surface.NextAfter(s)) {
-        s->Clear();
-    }
-    surface.Clear();
-
-    SCurve *c;
-    for(c = curve.First(); c; c = curve.NextAfter(c)) {
-        c->Clear();
-    }
-    curve.Clear();
-}
index 0a827761b9cae9cc993c756372d9c5f85c44d9be..9e03a83c10d67039d71eb26e92ac3bff019118a4 100644 (file)
@@ -23,20 +23,20 @@ void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB,
     // Now we have to piecewise linearize the curve. If there's already an
     // identical curve in the shell, then follow that pwl exactly, otherwise
     // calculate from scratch.
-    SCurve split, *existing = NULL, *se;
+    SCurve split, *existing = NULL;
     SBezier sbrev = *sb;
     sbrev.Reverse();
     bool backwards = false;
 #pragma omp critical(into)
     {
-        for(se = into->curve.First(); se; se = into->curve.NextAfter(se)) {
-            if(se->isExact) {
-                if(sb->Equals(&(se->exact))) {
-                    existing = se;
+        for(SCurve &se : into->curve) {
+            if(se.isExact) {
+                if(sb->Equals(&(se.exact))) {
+                    existing = &se;
                     break;
                 }
-                if(sbrev.Equals(&(se->exact))) {
-                    existing = se;
+                if(sbrev.Equals(&(se.exact))) {
+                    existing = &se;
                     backwards = true;
                     break;
                 }
@@ -332,15 +332,14 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
                 shext = agnstA;
             }
             bool foundExact = false;
-            SCurve *sc;
-            for(sc = shext->curve.First(); sc; sc = shext->curve.NextAfter(sc)) {
-                if(sc->source == SCurve::Source::INTERSECTION) continue;
-                if(!sc->isExact) continue;
-                if((sc->surfA != sext->h) && (sc->surfB != sext->h)) continue;
+            for(SCurve &sc : shext->curve) {
+                if(sc.source == SCurve::Source::INTERSECTION) continue;
+                if(!sc.isExact) continue;
+                if((sc.surfA != sext->h) && (sc.surfB != sext->h)) continue;
                 // we have a curve belonging to the curved surface and not the plane.
                 // does it lie completely in the plane?
-                if(splane->ContainsPlaneCurve(sc)) {
-                    SBezier bezier = sc->exact;
+                if(splane->ContainsPlaneCurve(&sc)) {
+                    SBezier bezier = sc.exact;
                     AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
                     foundExact = true;
                 }
@@ -571,10 +570,9 @@ bool SSurface::ContainsPlaneCurve(SCurve *sc) const {
 void SShell::MakeCoincidentEdgesInto(SSurface *proto, bool sameNormal,
                                      SEdgeList *el, SShell *useCurvesFrom)
 {
-    SSurface *ss;
-    for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
-        if(proto->CoincidentWith(ss, sameNormal)) {
-            ss->MakeEdgesInto(this, el, SSurface::MakeAs::XYZ, useCurvesFrom);
+    for(SSurface &ss : surface) {
+        if(proto->CoincidentWith(&ss, sameNormal)) {
+            ss.MakeEdgesInto(this, el, SSurface::MakeAs::XYZ, useCurvesFrom);
         }
     }
 
index d02f963802e8448de52b526a52c68e6d7ee9cfbf..464bce624b59b81565bb15f31bcd295f62e60116 100644 (file)
@@ -426,7 +426,7 @@ void SContour::UvTriangulateInto(SMesh *m, SSurface *srf) {
             if (i == l.n-1) {
                 end = true;
             }
-            if (end) {  // triangulate the fan and tag the verticies
+            if (end) {  // triangulate the fan and tag the vertices
                 if (j > 3) {
                     Vector center = l[pstart+1].p.Plus(l[pstart+j-1].p).ScaledBy(0.5);
                     for (int x=0; x<j; x++) {
@@ -597,11 +597,11 @@ void SPolygon::UvGridTriangulateInto(SMesh *mesh, SSurface *srf) {
     srf->MakeTriangulationGridInto(&lj, 0, 1, /*swapped=*/false, 0);
 
     // force 2nd order grid to have at least 4 segments in each direction
-    if ((li.n < 5) && (srf->degm>1)) { // 4 segments minimun
+    if ((li.n < 5) && (srf->degm>1)) { // 4 segments minimum
         li.Clear();
         li.Add(&v[0]);li.Add(&v[1]);li.Add(&v[2]);li.Add(&v[3]);li.Add(&v[4]);
     }
-    if ((lj.n < 5) && (srf->degn>1)) { // 4 segments minimun
+    if ((lj.n < 5) && (srf->degn>1)) { // 4 segments minimum
         lj.Clear();
         lj.Add(&v[0]);lj.Add(&v[1]);lj.Add(&v[2]);lj.Add(&v[3]);lj.Add(&v[4]);
     }
@@ -681,7 +681,7 @@ void SPolygon::UvGridTriangulateInto(SMesh *mesh, SSurface *srf) {
                     if (!bottom[j]) // add our own bottom edge
                         holes.AddEdge(a, b);
                 } else {
-                    if (prev_flag) // add our left neighbots right edge
+                    if (prev_flag) // add our left neighbors right edge
                         holes.AddEdge(a, d);
                     if (bottom[j]) // add our bottom neighbors top edge
                         holes.AddEdge(b, a);
index 1f719f671252fd7244a97a948fa92a2b7c99ca3a..4349eb36e4940a8f48b2140be7d92e7d377457b6 100644 (file)
@@ -8,22 +8,22 @@
 #include "solvespace.h"
 
 const Style::Default Style::Defaults[] = {
-    { { ACTIVE_GRP },   "ActiveGrp",    RGBf(1.0, 1.0, 1.0), 1.5, 4 },
-    { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0 },
-    { { INACTIVE_GRP }, "InactiveGrp",  RGBf(0.5, 0.3, 0.0), 1.5, 3 },
-    { { DATUM },        "Datum",        RGBf(0.0, 0.8, 0.0), 1.5, 0 },
-    { { SOLID_EDGE },   "SolidEdge",    RGBf(0.8, 0.8, 0.8), 1.0, 2 },
-    { { CONSTRAINT },   "Constraint",   RGBf(1.0, 0.1, 1.0), 1.0, 0 },
-    { { SELECTED },     "Selected",     RGBf(1.0, 0.0, 0.0), 1.5, 0 },
-    { { HOVERED },      "Hovered",      RGBf(1.0, 1.0, 0.0), 1.5, 0 },
-    { { CONTOUR_FILL }, "ContourFill",  RGBf(0.0, 0.1, 0.1), 1.0, 0 },
-    { { NORMALS },      "Normals",      RGBf(0.0, 0.4, 0.4), 1.0, 0 },
-    { { ANALYZE },      "Analyze",      RGBf(0.0, 1.0, 1.0), 3.0, 0 },
-    { { DRAW_ERROR },   "DrawError",    RGBf(1.0, 0.0, 0.0), 8.0, 0 },
-    { { DIM_SOLID },    "DimSolid",     RGBf(0.1, 0.1, 0.1), 1.0, 0 },
-    { { HIDDEN_EDGE },  "HiddenEdge",   RGBf(0.8, 0.8, 0.8), 1.0, 1 },
-    { { OUTLINE },      "Outline",      RGBf(0.8, 0.8, 0.8), 3.0, 5 },
-    { { 0 },            NULL,           RGBf(0.0, 0.0, 0.0), 0.0, 0 }
+    { { ACTIVE_GRP },   "ActiveGrp",    RGBf(1.0, 1.0, 1.0), 1.5, 4, true,  StipplePattern::CONTINUOUS },
+    { { CONSTRUCTION }, "Construction", RGBf(0.1, 0.7, 0.1), 1.5, 0, false, StipplePattern::CONTINUOUS },
+    { { INACTIVE_GRP }, "InactiveGrp",  RGBf(0.5, 0.3, 0.0), 1.5, 3, true,  StipplePattern::CONTINUOUS },
+    { { DATUM },        "Datum",        RGBf(0.0, 0.8, 0.0), 1.5, 0, true,  StipplePattern::CONTINUOUS },
+    { { SOLID_EDGE },   "SolidEdge",    RGBf(0.8, 0.8, 0.8), 1.0, 2, true,  StipplePattern::CONTINUOUS },
+    { { CONSTRAINT },   "Constraint",   RGBf(1.0, 0.1, 1.0), 1.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { SELECTED },     "Selected",     RGBf(1.0, 0.0, 0.0), 1.5, 0, true,  StipplePattern::CONTINUOUS },
+    { { HOVERED },      "Hovered",      RGBf(1.0, 1.0, 0.0), 1.5, 0, true,  StipplePattern::CONTINUOUS },
+    { { CONTOUR_FILL }, "ContourFill",  RGBf(0.0, 0.1, 0.1), 1.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { NORMALS },      "Normals",      RGBf(0.0, 0.4, 0.4), 1.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { ANALYZE },      "Analyze",      RGBf(0.0, 1.0, 1.0), 3.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { DRAW_ERROR },   "DrawError",    RGBf(1.0, 0.0, 0.0), 8.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { DIM_SOLID },    "DimSolid",     RGBf(0.1, 0.1, 0.1), 1.0, 0, true,  StipplePattern::CONTINUOUS },
+    { { HIDDEN_EDGE },  "HiddenEdge",   RGBf(0.8, 0.8, 0.8), 1.0, 1, true,  StipplePattern::DASH },
+    { { OUTLINE },      "Outline",      RGBf(0.8, 0.8, 0.8), 3.0, 5, true,  StipplePattern::CONTINUOUS },
+    { { 0 },            NULL,           RGBf(0.0, 0.0, 0.0), 0.0, 0, true,  StipplePattern::CONTINUOUS }
 };
 
 std::string Style::CnfColor(const std::string &prefix) {
@@ -32,9 +32,18 @@ std::string Style::CnfColor(const std::string &prefix) {
 std::string Style::CnfWidth(const std::string &prefix) {
     return "Style_" + prefix + "_Width";
 }
+std::string Style::CnfStippleType(const std::string &prefix) {
+    return "Style_" + prefix + "_StippleType";
+}
+std::string Style::CnfStippleScale(const std::string &prefix) {
+    return "Style_" + prefix + "_StippleScale";
+}
 std::string Style::CnfTextHeight(const std::string &prefix) {
     return "Style_" + prefix + "_TextHeight";
 }
+std::string Style::CnfExportable(const std::string &prefix) {
+    return "Style_" + prefix + "_Exportable";
+}
 
 std::string Style::CnfPrefixToName(const std::string &prefix) {
     std::string name = "#def-";
@@ -97,12 +106,19 @@ void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
     s->textOrigin    = TextOrigin::NONE;
     s->textAngle     = 0;
     s->visible       = true;
-    s->exportable    = true;
+    s->exportable    = (factory)
+                        ? d->exportable
+                        : settings->ThawBool(CnfExportable(d->cnfPrefix), d->exportable);
     s->filled        = false;
     s->fillColor     = RGBf(0.3, 0.3, 0.3);
-    s->stippleType   = (d->h.v == Style::HIDDEN_EDGE) ? StipplePattern::DASH
-                                                      : StipplePattern::CONTINUOUS;
-    s->stippleScale  = 15.0;
+    s->stippleType   = (factory)
+                        ? d->stippleType
+                        : Style::StipplePatternFromString(
+                            settings->ThawString(CnfStippleType(d->cnfPrefix),
+                            StipplePatternName(d->stippleType)));
+    s->stippleScale  = (factory)
+                        ? 15.0
+                        : settings->ThawFloat(CnfStippleScale(d->cnfPrefix), 15.0);
     s->zIndex        = d->zIndex;
 }
 
@@ -120,7 +136,10 @@ void Style::FreezeDefaultStyles(Platform::SettingsRef settings) {
     for(d = &(Defaults[0]); d->h.v; d++) {
         settings->FreezeColor(CnfColor(d->cnfPrefix), Color(d->h));
         settings->FreezeFloat(CnfWidth(d->cnfPrefix), (float)Width(d->h));
+        settings->FreezeString(CnfStippleType(d->cnfPrefix), StipplePatternName(d->h));
+        settings->FreezeFloat(CnfStippleScale(d->cnfPrefix), (float)StippleScale(d->h));
         settings->FreezeFloat(CnfTextHeight(d->cnfPrefix), (float)TextHeight(d->h));
+        settings->FreezeBool(CnfExportable(d->cnfPrefix), Exportable(d->h.v));
     }
 }
 
@@ -347,11 +366,62 @@ hStyle Style::ForEntity(hEntity he) {
     return hs;
 }
 
+StipplePattern Style::StipplePatternFromString(std::string name) {
+    std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+    if(name == "continuous") {
+        return StipplePattern::CONTINUOUS;
+    } else if(name == "shortdash") {
+        return StipplePattern::SHORT_DASH;
+    } else if(name == "dash") {
+        return StipplePattern::DASH;
+    } else if(name == "longdash") {
+        return StipplePattern::LONG_DASH;
+    } else if(name == "dashdot") {
+        return StipplePattern::DASH_DOT;
+    } else if(name == "dashdotdot") {
+        return StipplePattern::DASH_DOT_DOT;
+    } else if(name == "dot") {
+        return StipplePattern::DOT;
+    } else if(name == "freehand") {
+        return StipplePattern::FREEHAND;
+    } else if(name == "zigzag") {
+        return StipplePattern::ZIGZAG;
+    }
+
+    return StipplePattern::CONTINUOUS;
+}
+
 StipplePattern Style::PatternType(hStyle hs) {
     Style *s = Get(hs);
     return s->stippleType;
 }
 
+std::string Style::StipplePatternName(hStyle hs) {
+    Style *s = Get(hs);
+    return StipplePatternName(s->stippleType);
+}
+
+std::string Style::StipplePatternName(StipplePattern stippleType) {
+    switch(stippleType) {
+        case StipplePattern::CONTINUOUS:   return "Continuous";
+        case StipplePattern::SHORT_DASH:   return "ShortDash";
+        case StipplePattern::DASH:         return "Dash";
+        case StipplePattern::LONG_DASH:    return "LongDash";
+        case StipplePattern::DASH_DOT:     return "DashDot";
+        case StipplePattern::DASH_DOT_DOT: return "DashDotDot";
+        case StipplePattern::DOT:          return "Dot";
+        case StipplePattern::FREEHAND:     return "FreeHand";
+        case StipplePattern::ZIGZAG:       return "ZigZag";
+    }
+
+    return "Continuous";
+}
+
+double Style::StippleScale(hStyle hs) {
+    Style *s = Get(hs);
+    return s->stippleScale;
+}
+
 double Style::StippleScaleMm(hStyle hs) {
     Style *s = Get(hs);
     if(s->widthAs == UnitsAs::MM) {
@@ -383,6 +453,7 @@ void TextWindow::ScreenShowStyleInfo(int link, uint32_t v) {
 void TextWindow::ScreenLoadFactoryDefaultStyles(int link, uint32_t v) {
     Style::LoadFactoryDefaults();
     SS.TW.GoToScreen(Screen::LIST_OF_STYLES);
+    SS.GW.persistentDirty = true;
 }
 
 void TextWindow::ScreenCreateCustomStyle(int link, uint32_t v) {
@@ -399,14 +470,13 @@ void TextWindow::ShowListOfStyles() {
     Printf(true, "%Ft color  style-name");
 
     bool darkbg = false;
-    Style *s;
-    for(s = SK.style.First(); s; s = SK.style.NextAfter(s)) {
+    for(Style &s : SK.style) {
         Printf(false, "%Bp  %Bz   %Bp   %Fl%Ll%f%D%s%E",
             darkbg ? 'd' : 'a',
-            &s->color,
+            &s.color,
             darkbg ? 'd' : 'a',
-            ScreenShowStyleInfo, s->h.v,
-            s->DescriptionString().c_str());
+            ScreenShowStyleInfo, s.h.v,
+            s.DescriptionString().c_str());
 
         darkbg = !darkbg;
     }
@@ -493,7 +563,7 @@ void TextWindow::ScreenChangeStyleMetric(int link, uint32_t v) {
     if(units == Style::UnitsAs::PIXELS) {
         edit_value = ssprintf("%.2f", val);
     } else {
-        edit_value = SS.MmToString(val);
+        edit_value = SS.MmToString(val, true);
     }
     SS.TW.ShowEditControl(col, edit_value);
     SS.TW.edit.style = hs;
@@ -850,17 +920,19 @@ void TextWindow::ShowStyleInfo() {
             ((uint32_t)s->textOrigin & (uint32_t)Style::TextOrigin::TOP) ? RADIO_TRUE : RADIO_FALSE);
     }
 
-    if(s->h.v >= Style::FIRST_CUSTOM) {
-        Printf(false, "");
+    Printf(false, "");
 
+    if(s->h.v >= Style::FIRST_CUSTOM) {
         Printf(false, "  %Fd%D%f%Lv%s  show these objects on screen%E",
                 s->h.v, &ScreenChangeStyleYesNo,
                 s->visible ? CHECK_TRUE : CHECK_FALSE);
+    }
 
-        Printf(false, "  %Fd%D%f%Le%s  export these objects%E",
-                s->h.v, &ScreenChangeStyleYesNo,
-                s->exportable ? CHECK_TRUE : CHECK_FALSE);
+    Printf(false, "  %Fd%D%f%Le%s  export these objects%E",
+            s->h.v, &ScreenChangeStyleYesNo,
+            s->exportable ? CHECK_TRUE : CHECK_FALSE);
 
+    if(s->h.v >= Style::FIRST_CUSTOM) {
         Printf(false, "");
         Printf(false, "To assign lines or curves to this style,");
         Printf(false, "right-click them on the drawing.");
index 1119c3431dcef82f16f083809101e061bb33fda3..c513796f619f87df0ade9e53612a4a5d8b9b1370 100644 (file)
 //-----------------------------------------------------------------------------
 #include "solvespace.h"
 
-// This tolerance is used to determine whether two (linearized) constraints
-// are linearly dependent. If this is too small, then we will attempt to
-// solve truly inconsistent systems and fail. But if it's too large, then
-// we will give up on legitimate systems like a skinny right angle triangle by
-// its hypotenuse and long side.
-const double System::RANK_MAG_TOLERANCE = 1e-4;
+#include <Eigen/Core>
+#include <Eigen/SparseQR>
 
 // The solver will converge all unknowns to within this tolerance. This must
 // always be much less than LENGTH_EPS, and in practice should be much less.
 const double System::CONVERGE_TOLERANCE = (LENGTH_EPS/(1e2));
 
-bool System::WriteJacobian(int tag) {
-
-    int j = 0;
-    for(auto &p : param) {
-        if(j >= MAX_UNKNOWNS)
-            return false;
+constexpr size_t LikelyPartialCountPerEq = 10;
 
-        if(p.tag != tag)
-            continue;
-        mat.param[j] = p.h;
-        j++;
+bool System::WriteJacobian(int tag) {
+    // Clear all
+    mat.param.clear();
+    mat.eq.clear();
+    mat.A.sym.setZero();
+    mat.B.sym.clear();
+
+    for(Param &p : param) {
+        if(p.tag != tag) continue;
+        mat.param.push_back(p.h);
     }
-    mat.n = j;
-
-    int i = 0;
+    mat.n = mat.param.size();
 
-    for(auto &e : eq) {
-        if(i >= MAX_UNKNOWNS) return false;
-
-        if(e.tag != tag)
-            continue;
-
-        mat.eq[i] = e.h;
-        Expr *f   = e.e->DeepCopyWithParamsAsPointers(&param, &(SK.param));
-        f = f->FoldConstants();
+    for(Equation &e : eq) {
+        if(e.tag != tag) continue;
+        mat.eq.push_back(&e);
+    }
+    mat.m = mat.eq.size();
+    mat.A.sym.resize(mat.m, mat.n);
+    mat.A.sym.reserve(Eigen::VectorXi::Constant(mat.n, LikelyPartialCountPerEq));
+
+    // Fill the param id to index map
+    std::map<uint32_t, int> paramToIndex;
+    for(int j = 0; j < mat.n; j++) {
+        paramToIndex[mat.param[j].v] = j;
+    }
 
-        // Hash table (61 bits) to accelerate generation of zero partials.
-        uint64_t scoreboard = f->ParamsUsed();
-        for(j = 0; j < mat.n; j++) {
-            Expr *pd;
-            if(scoreboard & ((uint64_t)1 << (mat.param[j].v % 61)) &&
-                f->DependsOn(mat.param[j]))
-            {
-                pd = f->PartialWrt(mat.param[j]);
-                pd = pd->FoldConstants();
-                pd = pd->DeepCopyWithParamsAsPointers(&param, &(SK.param));
-            } else {
-                pd = Expr::From(0.0);
-            }
-            mat.A.sym[i][j] = pd;
+    if(mat.eq.size() >= MAX_UNKNOWNS) {
+        return false;
+    }
+    std::vector<hParam> paramsUsed;
+    // In some experimenting, this is almost always the right size.
+    // Value is usually between 0 and 20, comes from number of constraints?
+    mat.B.sym.reserve(mat.eq.size());
+    for(size_t i = 0; i < mat.eq.size(); i++) {
+        Equation *e = mat.eq[i];
+        if(e->tag != tag) continue;
+        // Simplify (fold) then deep-copy the current equation.
+        Expr *f = e->e->FoldConstants();
+        f = f->DeepCopyWithParamsAsPointers(&param, &(SK.param));
+
+        paramsUsed.clear();
+        f->ParamsUsedList(&paramsUsed);
+
+        for(hParam &p : paramsUsed) {
+            // Find the index of this parameter
+            auto it = paramToIndex.find(p.v);
+            if(it == paramToIndex.end()) continue;
+            // this is the parameter index
+            const int j = it->second;
+            // compute partial derivative of f
+            Expr *pd = f->PartialWrt(p);
+            pd = pd->FoldConstants();
+            if(pd->IsZeroConst())
+                continue;
+            mat.A.sym.insert(i, j) = pd;
         }
-        mat.B.sym[i] = f;
-        i++;
+        paramsUsed.clear();
+        mat.B.sym.push_back(f);
     }
-    mat.m = i;
-
     return true;
 }
 
 void System::EvalJacobian() {
-    int i, j;
-    for(i = 0; i < mat.m; i++) {
-        for(j = 0; j < mat.n; j++) {
-            mat.A.num[i][j] = (mat.A.sym[i][j])->Eval();
+    using namespace Eigen;
+    mat.A.num.setZero();
+    mat.A.num.resize(mat.m, mat.n);
+    const int size = mat.A.sym.outerSize();
+
+    for(int k = 0; k < size; k++) {
+        for(SparseMatrix <Expr *>::InnerIterator it(mat.A.sym, k); it; ++it) {
+            double value = it.value()->Eval();
+            if(EXACT(value == 0.0)) continue;
+            mat.A.num.insert(it.row(), it.col()) = value;
         }
     }
+    mat.A.num.makeCompressed();
 }
 
 bool System::IsDragged(hParam p) {
-    hParam *pp;
-    for(pp = dragged.First(); pp; pp = dragged.NextAfter(pp)) {
-        if(p == *pp) return true;
+    const auto b = dragged.begin();
+    const auto e = dragged.end();
+    return e != std::find(b, e, p);
+}
+
+Param *System::GetLastParamSubstitution(Param *p) {
+    Param *current = p;
+    while(current->substd != NULL) {
+        current = current->substd;
+        if(current == p) {
+            // Break the loop
+            current->substd = NULL;
+            break;
+        }
+    }
+    return current;
+}
+
+void System::SortSubstitutionByDragged(Param *p) {
+    std::vector<Param *> subsParams;
+    Param *by = NULL;
+    Param *current = p;
+    while(current != NULL) {
+        subsParams.push_back(current);
+        if(IsDragged(current->h)) {
+            by = current;
+        }
+        current = current->substd;
+    }
+    if(by == NULL) by = p;
+    for(Param *p : subsParams) {
+       if(p == by) continue;
+       p->substd = by;
+       p->tag = VAR_SUBSTITUTED;
+    }
+    by->substd = NULL;
+    by->tag = 0;
+}
+
+void System::SubstituteParamsByLast(Expr *e) {
+    ssassert(e->op != Expr::Op::PARAM_PTR, "Expected an expression that refer to params via handles");
+
+    if(e->op == Expr::Op::PARAM) {
+        Param *p = param.FindByIdNoOops(e->parh);
+        if(p != NULL) {
+            Param *s = GetLastParamSubstitution(p);
+            if(s != NULL) {
+                e->parh = s->h;
+            }
+        }
+    } else {
+        int c = e->Children();
+        if(c >= 1) {
+            SubstituteParamsByLast(e->a);
+            if(c >= 2) SubstituteParamsByLast(e->b);
+        }
     }
-    return false;
 }
 
 void System::SolveBySubstitution() {
@@ -102,172 +173,114 @@ void System::SolveBySubstitution() {
                 continue;
             }
 
-            if(IsDragged(a)) {
-                // A is being dragged, so A should stay, and B should go
-                std::swap(a, b);
+            if(a.v == b.v) {
+                teq.tag = EQ_SUBSTITUTED;
+                continue;
             }
 
-            for(auto &req : eq) {
-                req.e->Substitute(a, b); // A becomes B, B unchanged
-            }
-            for(auto &rp : param) {
-                if(rp.substd == a) {
-                    rp.substd = b;
+            Param *pa = param.FindById(a);
+            Param *pb = param.FindById(b);
+
+            // Take the last substitution of parameter a
+            // This resulted in creation of substitution chains
+            Param *last = GetLastParamSubstitution(pa);
+            last->substd = pb;
+            last->tag = VAR_SUBSTITUTED;
+
+            if(pb->substd != NULL) {
+                // Break the loops
+                GetLastParamSubstitution(pb);
+                // if b loop was broken
+                if(pb->substd == NULL) {
+                    // Clear substitution
+                    pb->tag = 0;
                 }
             }
-            Param *ptr = param.FindById(a);
-            ptr->tag = VAR_SUBSTITUTED;
-            ptr->substd = b;
-
             teq.tag = EQ_SUBSTITUTED;
         }
     }
-}
 
-//-----------------------------------------------------------------------------
-// Calculate the rank of the Jacobian matrix, by Gram-Schimdt orthogonalization
-// in place. A row (~equation) is considered to be all zeros if its magnitude
-// is less than the tolerance RANK_MAG_TOLERANCE.
-//-----------------------------------------------------------------------------
-int System::CalculateRank() {
-    // Actually work with magnitudes squared, not the magnitudes
-    double rowMag[MAX_UNKNOWNS] = {};
-    double tol = RANK_MAG_TOLERANCE*RANK_MAG_TOLERANCE;
+    //
+    for(Param &p : param) {
+        SortSubstitutionByDragged(&p);
+    }
 
-    int i, iprev, j;
-    int rank = 0;
+    // Substitute all the equations
+    for(auto &req : eq) {
+        SubstituteParamsByLast(req.e);
+    }
 
-    for(i = 0; i < mat.m; i++) {
-        // Subtract off this row's component in the direction of any
-        // previous rows
-        for(iprev = 0; iprev < i; iprev++) {
-            if(rowMag[iprev] <= tol) continue; // ignore zero rows
-
-            double dot = 0;
-            for(j = 0; j < mat.n; j++) {
-                dot += (mat.A.num[iprev][j]) * (mat.A.num[i][j]);
-            }
-            for(j = 0; j < mat.n; j++) {
-                mat.A.num[i][j] -= (dot/rowMag[iprev])*mat.A.num[iprev][j];
-            }
-        }
-        // Our row is now normal to all previous rows; calculate the
-        // magnitude of what's left
-        double mag = 0;
-        for(j = 0; j < mat.n; j++) {
-            mag += (mat.A.num[i][j]) * (mat.A.num[i][j]);
-        }
-        if(mag > tol) {
-            rank++;
-        }
-        rowMag[i] = mag;
+    // Substitute all the parameters with last substitutions
+    for(auto &p : param) {
+        if(p.substd == NULL) continue;
+        p.substd = GetLastParamSubstitution(p.substd);
     }
+}
 
-    return rank;
+//-----------------------------------------------------------------------------
+// Calculate the rank of the Jacobian matrix
+//-----------------------------------------------------------------------------
+int System::CalculateRank() {
+    using namespace Eigen;
+    if(mat.n == 0 || mat.m == 0) return 0;
+    SparseQR <SparseMatrix<double>, COLAMDOrdering<int>> solver;
+    solver.compute(mat.A.num);
+    int result = solver.rank();
+    return result;
 }
 
-bool System::TestRank(int *rank) {
+bool System::TestRank(int *dof) {
     EvalJacobian();
     int jacobianRank = CalculateRank();
-    if(rank) *rank = jacobianRank;
+    // We are calculating dof based on real rank, not mat.m.
+    // Using this approach we can calculate real dof even when redundant is allowed.
+    if(dof != NULL) *dof = mat.n - jacobianRank;
     return jacobianRank == mat.m;
 }
 
-bool System::SolveLinearSystem(double X[], double A[][MAX_UNKNOWNS],
-                               double B[], int n)
+bool System::SolveLinearSystem(const Eigen::SparseMatrix <double> &A,
+                               const Eigen::VectorXd &B, Eigen::VectorXd *X)
 {
-    // Gaussian elimination, with partial pivoting. It's an error if the
-    // matrix is singular, because that means two constraints are
-    // equivalent.
-    int i, j, ip, jp, imax = 0;
-    double max, temp;
-
-    for(i = 0; i < n; i++) {
-        // We are trying eliminate the term in column i, for rows i+1 and
-        // greater. First, find a pivot (between rows i and N-1).
-        max = 0;
-        for(ip = i; ip < n; ip++) {
-            if(fabs(A[ip][i]) > max) {
-                imax = ip;
-                max = fabs(A[ip][i]);
-            }
-        }
-        // Don't give up on a singular matrix unless it's really bad; the
-        // assumption code is responsible for identifying that condition,
-        // so we're not responsible for reporting that error.
-        if(fabs(max) < 1e-20) continue;
-
-        // Swap row imax with row i
-        for(jp = 0; jp < n; jp++) {
-            swap(A[i][jp], A[imax][jp]);
-        }
-        swap(B[i], B[imax]);
-
-        // For rows i+1 and greater, eliminate the term in column i.
-        for(ip = i+1; ip < n; ip++) {
-            temp = A[ip][i]/A[i][i];
-
-            for(jp = i; jp < n; jp++) {
-                A[ip][jp] -= temp*(A[i][jp]);
-            }
-            B[ip] -= temp*B[i];
-        }
-    }
-
-    // We've put the matrix in upper triangular form, so at this point we
-    // can solve by back-substitution.
-    for(i = n - 1; i >= 0; i--) {
-        if(fabs(A[i][i]) < 1e-20) continue;
-
-        temp = B[i];
-        for(j = n - 1; j > i; j--) {
-            temp -= X[j]*A[i][j];
-        }
-        X[i] = temp / A[i][i];
-    }
-
-    return true;
+    if(A.outerSize() == 0) return true;
+    using namespace Eigen;
+    SparseQR<SparseMatrix<double>, COLAMDOrdering<int>> solver;
+    //SimplicialLDLT<SparseMatrix<double>> solver;
+    solver.compute(A);
+    *X = solver.solve(B);
+    return (solver.info() == Success);
 }
 
 bool System::SolveLeastSquares() {
-    int r, c, i;
-
+    using namespace Eigen;
     // Scale the columns; this scale weights the parameters for the least
     // squares solve, so that we can encourage the solver to make bigger
     // changes in some parameters, and smaller in others.
-    for(c = 0; c < mat.n; c++) {
+    mat.scale = VectorXd::Ones(mat.n);
+    for(int c = 0; c < mat.n; c++) {
         if(IsDragged(mat.param[c])) {
             // It's least squares, so this parameter doesn't need to be all
             // that big to get a large effect.
-            mat.scale[c] = 1/20.0;
-        } else {
-            mat.scale[c] = 1;
-        }
-        for(r = 0; r < mat.m; r++) {
-            mat.A.num[r][c] *= mat.scale[c];
+            mat.scale[c] = 1 / 20.0;
         }
     }
 
-    // Write A*A'
-    for(r = 0; r < mat.m; r++) {
-        for(c = 0; c < mat.m; c++) {  // yes, AAt is square
-            double sum = 0;
-            for(i = 0; i < mat.n; i++) {
-                sum += mat.A.num[r][i]*mat.A.num[c][i];
-            }
-            mat.AAt[r][c] = sum;
+    const int size = mat.A.num.outerSize();
+    for(int k = 0; k < size; k++) {
+        for(SparseMatrix<double>::InnerIterator it(mat.A.num, k); it; ++it) {
+            it.valueRef() *= mat.scale[it.col()];
         }
     }
 
-    if(!SolveLinearSystem(mat.Z, mat.AAt, mat.B.num, mat.m)) return false;
+    SparseMatrix<double> AAt = mat.A.num * mat.A.num.transpose();
+    AAt.makeCompressed();
+    VectorXd z(mat.n);
 
-    // And multiply that by A' to get our solution.
-    for(c = 0; c < mat.n; c++) {
-        double sum = 0;
-        for(i = 0; i < mat.m; i++) {
-            sum += mat.A.num[i][c]*mat.Z[i];
-        }
-        mat.X[c] = sum * mat.scale[c];
+    if(!SolveLinearSystem(AAt, mat.B.num, &z)) return false;
+
+    mat.X = mat.A.num.transpose() * z;
+
+    for(int c = 0; c < mat.n; c++) {
+        mat.X[c] *= mat.scale[c];
     }
     return true;
 }
@@ -279,6 +292,7 @@ bool System::NewtonSolve(int tag) {
     int i;
 
     // Evaluate the functions at our operating point.
+    mat.B.num = Eigen::VectorXd(mat.m);
     for(i = 0; i < mat.m; i++) {
         mat.B.num[i] = (mat.B.sym[i])->Eval();
     }
@@ -405,26 +419,26 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
 {
     WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g);
 
-    int i;
     bool rankOk;
 
 /*
+    int x;
     dbp("%d equations", eq.n);
-    for(i = 0; i < eq.n; i++) {
-        dbp("  %.3f = %s = 0", eq[i].e->Eval(), eq[i].e->Print());
+    for(x = 0; x < eq.n; x++) {
+        dbp("  %.3f = %s = 0", eq[x].e->Eval(), eq[x].e->Print());
     }
     dbp("%d parameters", param.n);
-    for(i = 0; i < param.n; i++) {
-        dbp("   param %08x at %.3f", param[i].h.v, param[i].val);
+    for(x = 0; x < param.n; x++) {
+        dbp("   param %08x at %.3f", param[x].h.v, param[x].val);
     } */
 
     // All params and equations are assigned to group zero.
     param.ClearTags();
     eq.ClearTags();
 
-    // Solving by substitution eliminates duplicate e.g. H/V constraints, which can cause rank test
-    // to succeed even on overdefined systems, which will fail later.
-    if(!forceDofCheck) {
+    // Since we are suppressing dof calculation or allowing redundant, we
+    // can't / don't want to catch result of dof checking without substitution
+    if(g->suppressDofCalculation || g->allowRedundant || !forceDofCheck) {
         SolveBySubstitution();
     }
 
@@ -462,22 +476,21 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
     if(!WriteJacobian(0)) {
         return SolveResult::TOO_MANY_UNKNOWNS;
     }
-
-    rankOk = TestRank(rank);
+    // Clear dof value in order to have indication when dof is actually not calculated
+    if(dof != NULL) *dof = -1;
+    // We are suppressing or allowing redundant, so we no need to catch unsolveable + redundant
+    rankOk = (!g->suppressDofCalculation && !g->allowRedundant) ? TestRank(dof) : true;
 
     // And do the leftovers as one big system
     if(!NewtonSolve(0)) {
         goto didnt_converge;
     }
 
-    rankOk = TestRank(rank);
+    // Here we are want to calculate dof even when redundant is allowed, so just handle suppressing
+    rankOk = (!g->suppressDofCalculation) ? TestRank(dof) : true;
     if(!rankOk) {
         if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, forceDofCheck);
     } else {
-        // This is not the full Jacobian, but any substitutions or single-eq
-        // solves removed one equation and one unknown, therefore no effect
-        // on the number of DOF.
-        if(dof) *dof = CalculateDof();
         MarkParamsFree(andFindFree);
     }
     // System solved correctly, so write the new values back in to the
@@ -485,7 +498,7 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
     for(auto &p : param) {
         double val;
         if(p.tag == VAR_SUBSTITUTED) {
-            val = param.FindById(p.substd)->val;
+            val = p.substd->val;
         } else {
             val = p.val;
         }
@@ -499,12 +512,12 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
 didnt_converge:
     SK.constraint.ClearTags();
     // Not using range-for here because index is used in additional ways
-    for(i = 0; i < eq.n; i++) {
+    for(size_t i = 0; i < mat.eq.size(); i++) {
         if(fabs(mat.B.num[i]) > CONVERGE_TOLERANCE || IsReasonable(mat.B.num[i])) {
             // This constraint is unsatisfied.
-            if(!mat.eq[i].isFromConstraint()) continue;
+            if(!mat.eq[i]->h.isFromConstraint()) continue;
 
-            hConstraint hc = mat.eq[i].constraint();
+            hConstraint hc = mat.eq[i]->h.constraint();
             ConstraintBase *c = SK.constraint.FindByIdNoOops(hc);
             if(!c) continue;
             // Don't double-show constraints that generated multiple
@@ -534,11 +547,14 @@ SolveResult System::SolveRank(Group *g, int *rank, int *dof, List<hConstraint> *
         return SolveResult::TOO_MANY_UNKNOWNS;
     }
 
-    bool rankOk = TestRank(rank);
+    bool rankOk = TestRank(dof);
     if(!rankOk) {
-        if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, /*forceDofCheck=*/true);
+        // When we are testing with redundant allowed, we don't want to have additional info
+        // about redundants since this test is working only for single redundant constraint
+        if(!g->suppressDofCalculation && !g->allowRedundant) {
+            if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, true);
+        }
     } else {
-        if(dof) *dof = CalculateDof();
         MarkParamsFree(andFindFree);
     }
     return rankOk ? SolveResult::OKAY : SolveResult::REDUNDANT_OKAY;
@@ -549,6 +565,8 @@ void System::Clear() {
     param.Clear();
     eq.Clear();
     dragged.Clear();
+    mat.A.num.setZero();
+    mat.A.sym.setZero();
 }
 
 void System::MarkParamsFree(bool find) {
@@ -573,7 +591,3 @@ void System::MarkParamsFree(bool find) {
     }
 }
 
-int System::CalculateDof() {
-    return mat.n - mat.m;
-}
-
index 07d5cdeeaa45628dbe78ce66f04d1973af8340d3..ba5d977c324895afda62cddcef34a5e603a5e45d 100644 (file)
@@ -123,13 +123,18 @@ void TextWindow::ShowListOfGroups() {
               sprintf(sdof, "%-3d", dof);
             }
         }
+        std::string suffix;
+        if(g->forceToMesh || g->IsTriangleMeshAssembly()) {
+            suffix = " (∆)";
+        }
+
         bool ref = (g->h == Group::HGROUP_REFERENCES);
         Printf(false,
                "%Bp%Fd "
                "%Ft%s%Fb%D%f%Ll%s%E "
                "%Fb%s%D%f%Ll%s%E  "
                "%Fp%D%f%s%Ll%s%E "
-               "%Fl%Ll%D%f%s",
+               "%Fp%Ll%D%f%s%E%s",
                // Alternate between light and dark backgrounds, for readability
                backgroundParity ? 'd' : 'a',
                // Link that activates the group
@@ -146,7 +151,9 @@ void TextWindow::ShowListOfGroups() {
                ok ? ((warn && SS.checkClosedContour) ? "err" : sdof) : "",
                ok ? "" : "ERR",
                // Link to a screen that gives more details on the group
-               g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str());
+               g->suppress ? 'g' : 'l',
+               g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str(),
+               suffix.c_str());
 
         if(active) afterActive = true;
         backgroundParity = !backgroundParity;
@@ -254,6 +261,8 @@ void TextWindow::ScreenChangeGroupOption(int link, uint32_t v) {
 
         case 'e': g->allowRedundant = !(g->allowRedundant); break;
 
+        case 'D': g->suppressDofCalculation = !(g->suppressDofCalculation); break;
+
         case 'v': g->visible = !(g->visible); break;
 
         case 'd': g->allDimsReference = !(g->allDimsReference); break;
@@ -299,6 +308,23 @@ void TextWindow::ScreenChangeGroupScale(int link, uint32_t v) {
     SS.TW.edit.meaning = Edit::GROUP_SCALE;
     SS.TW.edit.group.v = v;
 }
+void TextWindow::ScreenChangeHelixPitch(int link, uint32_t v) {
+    Group *g = SK.GetGroup(SS.TW.shown.group);
+    double pitch = g->valB/SS.MmPerUnit();
+    SS.TW.ShowEditControl(3, ssprintf("%.8f", pitch));
+    SS.TW.edit.meaning = Edit::HELIX_PITCH;
+    SS.TW.edit.group.v = v;
+}
+void TextWindow::ScreenChangePitchOption(int link, uint32_t v) {
+    Group *g = SK.GetGroup(SS.TW.shown.group);
+    if(g->valB == 0.0) {
+        g->valB = SK.GetParam(g->h.param(7))->val * PI /
+              (SK.GetParam(g->h.param(3))->val);
+    } else {
+        g->valB = 0.0;
+    }
+    SS.GW.Invalidate();
+}
 void TextWindow::ScreenDeleteGroup(int link, uint32_t v) {
     SS.UndoRemember();
 
@@ -398,6 +424,26 @@ void TextWindow::ShowGroupInfo() {
     }
     Printf(false, "");
 
+    if(g->type == Group::Type::HELIX) {
+        Printf(false, "%Ft pitch - length per turn%E");
+
+        if (fabs(g->valB) != 0.0) {
+            Printf(false, "  %Ba %# %Fl%Ll%f%D[change]%E",
+            g->valB / SS.MmPerUnit(),
+            &TextWindow::ScreenChangeHelixPitch, g->h.v);
+        } else {
+            Printf(false, "  %Ba %# %E",
+              SK.GetParam(g->h.param(7))->val * PI /
+              ( (SK.GetParam(g->h.param(3))->val) * SS.MmPerUnit() ),
+              &TextWindow::ScreenChangeHelixPitch, g->h.v);
+        }
+        Printf(false, "   %Fd%f%LP%s  fixed",
+            &TextWindow::ScreenChangePitchOption,
+            g->valB != 0 ? CHECK_TRUE : CHECK_FALSE);
+
+        Printf(false, ""); // blank line    
+    }
+
     if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
        g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED ||
        g->type == Group::Type::HELIX) {
@@ -451,7 +497,7 @@ void TextWindow::ShowGroupInfo() {
         &TextWindow::ScreenChangeGroupOption,
         g->visible ? CHECK_TRUE : CHECK_FALSE);
 
-    if(!g->IsForcedToMeshBySource()) {
+    if(!g->IsForcedToMeshBySource() && !g->IsTriangleMeshAssembly()) {
         Printf(false, " %f%Lf%Fd%s  force NURBS surfaces to triangle mesh",
             &TextWindow::ScreenChangeGroupOption,
             g->forceToMesh ? CHECK_TRUE : CHECK_FALSE);
@@ -467,6 +513,10 @@ void TextWindow::ShowGroupInfo() {
         &TextWindow::ScreenChangeGroupOption,
         g->allowRedundant ? CHECK_TRUE : CHECK_FALSE);
 
+    Printf(false, " %f%LD%Fd%s  suppress dof calculation (improves solver performance)",
+        &TextWindow::ScreenChangeGroupOption,
+        g->suppressDofCalculation ? CHECK_TRUE : CHECK_FALSE);
+
     Printf(false, " %f%Ld%Fd%s  treat all dimensions as reference",
         &TextWindow::ScreenChangeGroupOption,
         g->allDimsReference ? CHECK_TRUE : CHECK_FALSE);
@@ -579,7 +629,7 @@ void TextWindow::ShowGroupSolveInfo() {
     }
 
     if(g->solved.timeout) {
-        Printf(true,  "%FxSome items in list have been ommitted%Fd");
+        Printf(true,  "%FxSome items in list have been omitted%Fd");
         Printf(false,  "%Fxbecause the operation timed out.%Fd");
     }
 
@@ -603,7 +653,7 @@ void TextWindow::ScreenStepDimFinish(int link, uint32_t v) {
     SS.TW.edit.meaning = Edit::STEP_DIM_FINISH;
     std::string edit_value;
     if(SS.TW.stepDim.isDistance) {
-        edit_value = SS.MmToString(SS.TW.stepDim.finish);
+        edit_value = SS.MmToString(SS.TW.stepDim.finish, true);
     } else {
         edit_value = ssprintf("%.3f", SS.TW.stepDim.finish);
     }
@@ -690,7 +740,7 @@ void TextWindow::ScreenChangeTangentArc(int link, uint32_t v) {
     switch(link) {
         case 'r': {
             SS.TW.edit.meaning = Edit::TANGENT_ARC_RADIUS;
-            SS.TW.ShowEditControl(3, SS.MmToString(SS.tangentArcRadius));
+            SS.TW.ShowEditControl(3, SS.MmToString(SS.tangentArcRadius, true));
             break;
         }
 
@@ -789,6 +839,15 @@ void TextWindow::EditControlDone(std::string s) {
             }
             break;
 
+        case Edit::HELIX_PITCH:  // stored in valB
+            if(Expr *e = Expr::From(s, /*popUpError=*/true)) {
+                double ev = e->Eval();
+                Group *g = SK.GetGroup(edit.group);
+                g->valB = ev * SS.MmPerUnit();
+                SS.MarkGroupDirty(g->h);
+            }
+            break;
+
         case Edit::GROUP_COLOR: {
             Vector rgb;
             if(sscanf(s.c_str(), "%lf, %lf, %lf", &rgb.x, &rgb.y, &rgb.z)==3) {
index 3e3392261bf97ce1e4cdbd87af661ab8ce34982a..b68c068080803fbb294a46110451d8ce23085dfe 100644 (file)
@@ -203,7 +203,7 @@ const TextWindow::Color TextWindow::fgColors[] = {
     { 'r', RGBi(  0,   0,   0) },  // Reverse   : black
     { 'x', RGBi(255,  20,  20) },  // Error     : red
     { 'i', RGBi(  0, 255, 255) },  // Info      : cyan
-    { 'g', RGBi(160, 160, 160) },
+    { 'g', RGBi(128, 128, 128) },  // Disabled  : gray
     { 'b', RGBi(200, 200, 200) },
     { 0,   RGBi(  0,   0,   0) }
 };
@@ -235,6 +235,7 @@ void TextWindow::Init() {
 
             using namespace std::placeholders;
             window->onClose = []() {
+                SS.TW.HideEditControl();
                 SS.GW.showTextWindow = false;
                 SS.GW.EnsureValidActives();
             };
@@ -348,8 +349,8 @@ void TextWindow::ClearScreen() {
     rows = 0;
 }
 
-// This message was addded when someone had too many fonts for the text window
-// Scrolling seemed to be broken, but was actaully at the MAX_ROWS.
+// This message was added when someone had too many fonts for the text window
+// Scrolling seemed to be broken, but was actually at the MAX_ROWS.
 static const char* endString = "    **** End of Text Screen ****";
 
 void TextWindow::Printf(bool halfLine, const char *fmt, ...) {
index bf6b59c59b7aaa9b6a3e412423ab0e65aa5a71bc..74764883aae222e13d93363d3953a50cee835fa3 100644 (file)
@@ -153,11 +153,18 @@ bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my, UiCanvas *canvas,
     double width, height;
     window->GetContentSize(&width, &height);
 
-    int x = 17, y = (int)(height - 52);
+    int x = 17, y = (int)(height - 21); // 20 is the menu bar height
 
-    // When changing these values, also change the asReference drawing code in drawentity.cpp.
+    // When changing these values, also change the asReference drawing code in drawentity.cpp
+    // as well as the "window->SetMinContentSize(720, 636);" in graphicswin.cpp
     int fudge = 8;
-    int h = 32*18 + 3*16 + fudge;
+    int h = 32*18 + 3*16 + fudge;   // Toolbar height = 18 icons * 32 pixels + 3 dividers * 16 pixels + fudge
+
+    if(h < y) {
+        // If there is enough vertical space leave up to 32 pixels between the menu bar and the toolbar.
+        y -= ((y - h) < 32) ? y - h : 32;
+    }
+
     int aleft = 0, aright = 66, atop = y+16+fudge/2, abot = y+16-h;
 
     bool withinToolbar =
index ddb2aa175b81c768d61d1d8c8d7a65b1042d99fb..e39afc79583f5134d74f957e4c1922324b6b0e49 100644 (file)
@@ -11,7 +11,7 @@
 #include FT_ADVANCES_H
 
 /* Yecch. Irritatingly, you need to do this nonsense to get the error string table,
-   since nobody thought to put this exact function into FreeType itsself. */
+   since nobody thought to put this exact function into FreeType itself. */
 #undef __FTERRORS_H__
 #define FT_ERRORDEF(e, v, s) { (e), (s) },
 #define FT_ERROR_START_LIST
index 026d57de7259c4cd9de0ea5d6c7492cd2cd26972..c4ffff2ba8809e7326fab778b06f72ba7af3d7f4 100644 (file)
--- a/src/ui.h
+++ b/src/ui.h
@@ -82,6 +82,7 @@ enum class Command : uint32_t {
     SHOW_GRID,
     DIM_SOLID_MODEL,
     PERSPECTIVE_PROJ,
+    EXPLODE_SKETCH,
     ONTO_WORKPLANE,
     NEAREST_ORTHO,
     NEAREST_ISO,
@@ -89,6 +90,7 @@ enum class Command : uint32_t {
     SHOW_TOOLBAR,
     SHOW_TEXT_WND,
     UNITS_INCHES,
+    UNITS_FEET_INCHES,
     UNITS_MM,
     UNITS_METERS,
     FULL_SCREEN,
@@ -170,6 +172,7 @@ enum class Command : uint32_t {
     // Help
     LOCALE,
     WEBSITE,
+    GITHUB,
     ABOUT,
 };
 
@@ -312,12 +315,14 @@ public:
         EXPORT_OFFSET         = 110,
         CANVAS_SIZE           = 111,
         G_CODE_DEPTH          = 112,
-        G_CODE_PASSES         = 113,
-        G_CODE_FEED           = 114,
-        G_CODE_PLUNGE_FEED    = 115,
-        AUTOSAVE_INTERVAL     = 116,
-        LIGHT_AMBIENT         = 117,
-        FIND_CONSTRAINT_TIMEOUT = 118,
+        G_CODE_SAFE_HEIGHT    = 113,
+        G_CODE_PASSES         = 114,
+        G_CODE_FEED           = 115,
+        G_CODE_PLUNGE_FEED    = 116,
+        AUTOSAVE_INTERVAL     = 117,
+        LIGHT_AMBIENT         = 118,
+        FIND_CONSTRAINT_TIMEOUT = 119,
+        EXPLODE_DISTANCE      = 120,
         // For TTF text
         TTF_TEXT              = 300,
         // For the step dimension screen
@@ -342,7 +347,9 @@ public:
         VIEW_PROJ_RIGHT       = 702,
         VIEW_PROJ_UP          = 703,
         // For tangent arc
-        TANGENT_ARC_RADIUS    = 800
+        TANGENT_ARC_RADIUS    = 800,
+        // For helix pitch
+        HELIX_PITCH           = 802
     };
     struct {
         bool        showAgain;
@@ -473,6 +480,8 @@ public:
     static void ScreenChangeExprA(int link, uint32_t v);
     static void ScreenChangeGroupName(int link, uint32_t v);
     static void ScreenChangeGroupScale(int link, uint32_t v);
+    static void ScreenChangeHelixPitch(int link, uint32_t v);
+    static void ScreenChangePitchOption(int link, uint32_t v);
     static void ScreenChangeLightDirection(int link, uint32_t v);
     static void ScreenChangeLightIntensity(int link, uint32_t v);
     static void ScreenChangeLightAmbient(int link, uint32_t v);
@@ -483,6 +492,7 @@ public:
     static void ScreenChangeExportMaxSegments(int link, uint32_t v);
     static void ScreenChangeCameraTangent(int link, uint32_t v);
     static void ScreenChangeGridSpacing(int link, uint32_t v);
+    static void ScreenChangeExplodeDistance(int link, uint32_t v);
     static void ScreenChangeDigitsAfterDecimal(int link, uint32_t v);
     static void ScreenChangeDigitsAfterDecimalDegree(int link, uint32_t v);
     static void ScreenChangeUseSIPrefixes(int link, uint32_t v);
@@ -535,6 +545,7 @@ public:
     Platform::MenuItemRef showGridMenuItem;
     Platform::MenuItemRef dimSolidModelMenuItem;
     Platform::MenuItemRef perspectiveProjMenuItem;
+    Platform::MenuItemRef explodeMenuItem;
     Platform::MenuItemRef showToolbarMenuItem;
     Platform::MenuItemRef showTextWndMenuItem;
     Platform::MenuItemRef fullScreenMenuItem;
@@ -542,6 +553,7 @@ public:
     Platform::MenuItemRef unitsMmMenuItem;
     Platform::MenuItemRef unitsMetersMenuItem;
     Platform::MenuItemRef unitsInchesMenuItem;
+    Platform::MenuItemRef unitsFeetInchesMenuItem;
 
     Platform::MenuItemRef inWorkplaneMenuItem;
     Platform::MenuItemRef in3dMenuItem;
@@ -610,6 +622,7 @@ public:
     void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin,
                                  double *wmin, bool usePerspective,
                                  const Camera &camera);
+    void ZoomToMouse(double delta);
     void LoopOverPoints(const std::vector<Entity *> &entities,
                         const std::vector<Constraint *> &constraints,
                         const std::vector<hEntity> &faces,
@@ -798,6 +811,8 @@ public:
     bool    showEdges;
     bool    showOutlines;
     bool    showFaces;
+    bool    showFacesDrawing;
+    bool    showFacesNonDrawing;
     bool    showMesh;
     void ToggleBool(bool *v);
 
@@ -828,7 +843,7 @@ public:
     void MouseLeftDoubleClick(double x, double y);
     void MouseMiddleOrRightDown(double x, double y);
     void MouseRightUp(double x, double y);
-    void MouseScroll(double x, double y, double delta);
+    void MouseScroll(double delta);
     void MouseLeave();
     bool KeyboardEvent(Platform::KeyboardEvent event);
     void EditControlDone(const std::string &s);
index 14d09ba35416b31495cbae9da96750dccc12d7c9..99067bc535f16370b8ed7a90016b17aba0047b52 100644 (file)
@@ -35,8 +35,29 @@ void TextWindow::ShowEditView() {
     Printf(false, "%Ba   %Ftout%E   (%3, %3, %3)", CO(n));
     Printf(false, "");
 
-    Printf(false, "The perspective may be changed in the");
-    Printf(false, "configuration screen.");
+    Printf(false, "%Ft perspective factor (0 for parallel)%E");
+    Printf(false, "%Ba   %# %Fl%Ll%f%D[change]%E",
+        SS.cameraTangent*1000,
+        &ScreenChangeCameraTangent, 0);
+
+    Printf(false, "");
+    Printf(false, "%Ft light direction               intensity");
+    for(int i = 0; i < 2; i++) {
+        Printf(false, "%Bp   #%d  (%2,%2,%2)%Fl%D%f%Ll[c]%E "
+                      "%2 %Fl%D%f%Ll[c]%E",
+            (i & 1) ? 'd' : 'a', i,
+            CO(SS.lightDir[i]), i, &ScreenChangeLightDirection,
+            SS.lightIntensity[i], i, &ScreenChangeLightIntensity);
+    }
+    Printf(false, "%Ba         ambient lighting     %2 %Fl%f%Ll[c]%E",
+        SS.ambientIntensity, &ScreenChangeLightAmbient);
+
+    Printf(false, "");
+    Printf(false, "%Ft explode distance%E");
+    Printf(false, "%Ba   %s %Fl%Ll%f%D[change]%E",
+        SS.MmToString(SS.explodeDistance).c_str(),
+        &ScreenChangeExplodeDistance, 0);
+
 }
 
 void TextWindow::ScreenChangeViewScale(int link, uint32_t v) {
@@ -51,9 +72,9 @@ void TextWindow::ScreenChangeViewToFullScale(int link, uint32_t v) {
 void TextWindow::ScreenChangeViewOrigin(int link, uint32_t v) {
     std::string edit_value =
         ssprintf("%s, %s, %s",
-            SS.MmToString(-SS.GW.offset.x).c_str(),
-            SS.MmToString(-SS.GW.offset.y).c_str(),
-            SS.MmToString(-SS.GW.offset.z).c_str());
+            SS.MmToString(-SS.GW.offset.x, true).c_str(),
+            SS.MmToString(-SS.GW.offset.y, true).c_str(),
+            SS.MmToString(-SS.GW.offset.z, true).c_str());
 
     SS.TW.edit.meaning = Edit::VIEW_ORIGIN;
     SS.TW.ShowEditControl(3, edit_value);
@@ -66,6 +87,34 @@ void TextWindow::ScreenChangeViewProjection(int link, uint32_t v) {
     SS.TW.ShowEditControl(10, edit_value);
 }
 
+void TextWindow::ScreenChangeLightDirection(int link, uint32_t v) {
+    SS.TW.ShowEditControl(8, ssprintf("%.2f, %.2f, %.2f", CO(SS.lightDir[v])));
+    SS.TW.edit.meaning = Edit::LIGHT_DIRECTION;
+    SS.TW.edit.i = v;
+}
+
+void TextWindow::ScreenChangeLightIntensity(int link, uint32_t v) {
+    SS.TW.ShowEditControl(31, ssprintf("%.2f", SS.lightIntensity[v]));
+    SS.TW.edit.meaning = Edit::LIGHT_INTENSITY;
+    SS.TW.edit.i = v;
+}
+
+void TextWindow::ScreenChangeLightAmbient(int link, uint32_t v) {
+    SS.TW.ShowEditControl(31, ssprintf("%.2f", SS.ambientIntensity));
+    SS.TW.edit.meaning = Edit::LIGHT_AMBIENT;
+    SS.TW.edit.i = 0;
+}
+
+void TextWindow::ScreenChangeCameraTangent(int link, uint32_t v) {
+    SS.TW.ShowEditControl(3, ssprintf("%.3f", 1000*SS.cameraTangent));
+    SS.TW.edit.meaning = Edit::CAMERA_TANGENT;
+}
+
+void TextWindow::ScreenChangeExplodeDistance(int link, uint32_t v) {
+    SS.TW.ShowEditControl(3, SS.MmToString(SS.explodeDistance, true));
+    SS.TW.edit.meaning = Edit::EXPLODE_DISTANCE;
+}
+
 bool TextWindow::EditControlDoneForView(const std::string &s) {
     switch(edit.meaning) {
         case Edit::VIEW_SCALE: {
index 3f81a9543e93bd20eed1bc2f27cd82c6e4962e4a..aecf31558739c25da5a58ab8caa8bad7e4c0a8b5 100644 (file)
Binary files a/test/constraint/equal_angle/normal.png and b/test/constraint/equal_angle/normal.png differ
index b1d538f1d35dd4f4a207232a392e437b039a29c6..60e7b924cb732e38937027fa925de8403efba680 100644 (file)
@@ -119,7 +119,7 @@ Param.val=-5.00000000000000000000
 AddParam
 
 Param.h.v.=00040011
-Param.val=5.00000000000000000000
+Param.val=5.00000000000000088818
 AddParam
 
 Param.h.v.=00040013
@@ -147,7 +147,7 @@ Param.val=10.00000000000000000000
 AddParam
 
 Param.h.v.=00060010
-Param.val=10.00000000000000000000
+Param.val=10.29878739785912600269
 AddParam
 
 Param.h.v.=00060011
@@ -155,7 +155,7 @@ Param.val=10.00000000000000000000
 AddParam
 
 Param.h.v.=00060013
-Param.val=5.00000000000000000000
+Param.val=5.29878739785912422633
 AddParam
 
 Param.h.v.=00060014
@@ -163,7 +163,7 @@ Param.val=5.00000000000000000000
 AddParam
 
 Param.h.v.=00070010
-Param.val=5.00000000000000000000
+Param.val=5.29878739785912422633
 AddParam
 
 Param.h.v.=00070011
@@ -171,7 +171,7 @@ Param.val=5.00000000000000000000
 AddParam
 
 Param.h.v.=00070013
-Param.val=10.00000000000000000000
+Param.val=10.29878739785912600269
 AddParam
 
 Param.h.v.=00070014
@@ -310,7 +310,7 @@ Entity.type=2001
 Entity.construction=0
 Entity.workplane.v=80020000
 Entity.actPoint.x=-5.00000000000000000000
-Entity.actPoint.y=5.00000000000000000000
+Entity.actPoint.y=5.00000000000000088818
 Entity.actVisible=1
 AddEntity
 
@@ -363,7 +363,7 @@ Entity.h.v=00060001
 Entity.type=2001
 Entity.construction=0
 Entity.workplane.v=80020000
-Entity.actPoint.x=10.00000000000000000000
+Entity.actPoint.x=10.29878739785912600269
 Entity.actPoint.y=10.00000000000000000000
 Entity.actVisible=1
 AddEntity
@@ -372,7 +372,7 @@ Entity.h.v=00060002
 Entity.type=2001
 Entity.construction=0
 Entity.workplane.v=80020000
-Entity.actPoint.x=5.00000000000000000000
+Entity.actPoint.x=5.29878739785912422633
 Entity.actPoint.y=5.00000000000000000000
 Entity.actVisible=1
 AddEntity
@@ -390,7 +390,7 @@ Entity.h.v=00070001
 Entity.type=2001
 Entity.construction=0
 Entity.workplane.v=80020000
-Entity.actPoint.x=5.00000000000000000000
+Entity.actPoint.x=5.29878739785912422633
 Entity.actPoint.y=5.00000000000000000000
 Entity.actVisible=1
 AddEntity
@@ -399,7 +399,7 @@ Entity.h.v=00070002
 Entity.type=2001
 Entity.construction=0
 Entity.workplane.v=80020000
-Entity.actPoint.x=10.00000000000000000000
+Entity.actPoint.x=10.29878739785912600269
 Entity.actPoint.y=5.00000000000000000000
 Entity.actVisible=1
 AddEntity
diff --git a/test/constraint/equal_angle/normal_old_version.slvs b/test/constraint/equal_angle/normal_old_version.slvs
new file mode 100644 (file)
index 0000000..b1d538f
--- /dev/null
@@ -0,0 +1,463 @@
+±²³SolveSpaceREVa
+
+
+Group.h.v=00000001
+Group.type=5000
+Group.name=#references
+Group.color=ff000000
+Group.skipFirst=0
+Group.predef.swapUV=0
+Group.predef.negateU=0
+Group.predef.negateV=0
+Group.visible=1
+Group.suppress=0
+Group.relaxConstraints=0
+Group.allowRedundant=0
+Group.allDimsReference=0
+Group.scale=1.00000000000000000000
+Group.remap={
+}
+AddGroup
+
+Group.h.v=00000002
+Group.type=5001
+Group.order=1
+Group.name=sketch-in-plane
+Group.activeWorkplane.v=80020000
+Group.color=ff000000
+Group.subtype=6000
+Group.skipFirst=0
+Group.predef.q.w=1.00000000000000000000
+Group.predef.origin.v=00010001
+Group.predef.swapUV=0
+Group.predef.negateU=0
+Group.predef.negateV=0
+Group.visible=1
+Group.suppress=0
+Group.relaxConstraints=0
+Group.allowRedundant=0
+Group.allDimsReference=0
+Group.scale=1.00000000000000000000
+Group.remap={
+}
+AddGroup
+
+Param.h.v.=00010010
+AddParam
+
+Param.h.v.=00010011
+AddParam
+
+Param.h.v.=00010012
+AddParam
+
+Param.h.v.=00010020
+Param.val=1.00000000000000000000
+AddParam
+
+Param.h.v.=00010021
+AddParam
+
+Param.h.v.=00010022
+AddParam
+
+Param.h.v.=00010023
+AddParam
+
+Param.h.v.=00020010
+AddParam
+
+Param.h.v.=00020011
+AddParam
+
+Param.h.v.=00020012
+AddParam
+
+Param.h.v.=00020020
+Param.val=0.50000000000000000000
+AddParam
+
+Param.h.v.=00020021
+Param.val=0.50000000000000000000
+AddParam
+
+Param.h.v.=00020022
+Param.val=0.50000000000000000000
+AddParam
+
+Param.h.v.=00020023
+Param.val=0.50000000000000000000
+AddParam
+
+Param.h.v.=00030010
+AddParam
+
+Param.h.v.=00030011
+AddParam
+
+Param.h.v.=00030012
+AddParam
+
+Param.h.v.=00030020
+Param.val=0.50000000000000000000
+AddParam
+
+Param.h.v.=00030021
+Param.val=-0.50000000000000000000
+AddParam
+
+Param.h.v.=00030022
+Param.val=-0.50000000000000000000
+AddParam
+
+Param.h.v.=00030023
+Param.val=-0.50000000000000000000
+AddParam
+
+Param.h.v.=00040010
+Param.val=-5.00000000000000000000
+AddParam
+
+Param.h.v.=00040011
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00040013
+Param.val=-10.00000000000000000000
+AddParam
+
+Param.h.v.=00040014
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00050010
+Param.val=-10.00000000000000000000
+AddParam
+
+Param.h.v.=00050011
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00050013
+Param.val=-5.00000000000000000000
+AddParam
+
+Param.h.v.=00050014
+Param.val=10.00000000000000000000
+AddParam
+
+Param.h.v.=00060010
+Param.val=10.00000000000000000000
+AddParam
+
+Param.h.v.=00060011
+Param.val=10.00000000000000000000
+AddParam
+
+Param.h.v.=00060013
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00060014
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00070010
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00070011
+Param.val=5.00000000000000000000
+AddParam
+
+Param.h.v.=00070013
+Param.val=10.00000000000000000000
+AddParam
+
+Param.h.v.=00070014
+Param.val=5.00000000000000000000
+AddParam
+
+Request.h.v=00000001
+Request.type=100
+Request.group.v=00000001
+Request.construction=0
+AddRequest
+
+Request.h.v=00000002
+Request.type=100
+Request.group.v=00000001
+Request.construction=0
+AddRequest
+
+Request.h.v=00000003
+Request.type=100
+Request.group.v=00000001
+Request.construction=0
+AddRequest
+
+Request.h.v=00000004
+Request.type=200
+Request.workplane.v=80020000
+Request.group.v=00000002
+Request.construction=0
+AddRequest
+
+Request.h.v=00000005
+Request.type=200
+Request.workplane.v=80020000
+Request.group.v=00000002
+Request.construction=0
+AddRequest
+
+Request.h.v=00000006
+Request.type=200
+Request.workplane.v=80020000
+Request.group.v=00000002
+Request.construction=0
+AddRequest
+
+Request.h.v=00000007
+Request.type=200
+Request.workplane.v=80020000
+Request.group.v=00000002
+Request.construction=0
+AddRequest
+
+Entity.h.v=00010000
+Entity.type=10000
+Entity.construction=0
+Entity.point[0].v=00010001
+Entity.normal.v=00010020
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00010001
+Entity.type=2000
+Entity.construction=1
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00010020
+Entity.type=3000
+Entity.construction=0
+Entity.point[0].v=00010001
+Entity.actNormal.w=1.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00020000
+Entity.type=10000
+Entity.construction=0
+Entity.point[0].v=00020001
+Entity.normal.v=00020020
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00020001
+Entity.type=2000
+Entity.construction=1
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00020020
+Entity.type=3000
+Entity.construction=0
+Entity.point[0].v=00020001
+Entity.actNormal.w=0.50000000000000000000
+Entity.actNormal.vx=0.50000000000000000000
+Entity.actNormal.vy=0.50000000000000000000
+Entity.actNormal.vz=0.50000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00030000
+Entity.type=10000
+Entity.construction=0
+Entity.point[0].v=00030001
+Entity.normal.v=00030020
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00030001
+Entity.type=2000
+Entity.construction=1
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00030020
+Entity.type=3000
+Entity.construction=0
+Entity.point[0].v=00030001
+Entity.actNormal.w=0.50000000000000000000
+Entity.actNormal.vx=-0.50000000000000000000
+Entity.actNormal.vy=-0.50000000000000000000
+Entity.actNormal.vz=-0.50000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00040000
+Entity.type=11000
+Entity.construction=0
+Entity.point[0].v=00040001
+Entity.point[1].v=00040002
+Entity.workplane.v=80020000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00040001
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=-5.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00040002
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=-10.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00050000
+Entity.type=11000
+Entity.construction=0
+Entity.point[0].v=00050001
+Entity.point[1].v=00050002
+Entity.workplane.v=80020000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00050001
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=-10.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00050002
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=-5.00000000000000000000
+Entity.actPoint.y=10.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00060000
+Entity.type=11000
+Entity.construction=0
+Entity.point[0].v=00060001
+Entity.point[1].v=00060002
+Entity.workplane.v=80020000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00060001
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=10.00000000000000000000
+Entity.actPoint.y=10.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00060002
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=5.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00070000
+Entity.type=11000
+Entity.construction=0
+Entity.point[0].v=00070001
+Entity.point[1].v=00070002
+Entity.workplane.v=80020000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00070001
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=5.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=00070002
+Entity.type=2001
+Entity.construction=0
+Entity.workplane.v=80020000
+Entity.actPoint.x=10.00000000000000000000
+Entity.actPoint.y=5.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=80020000
+Entity.type=10000
+Entity.construction=0
+Entity.point[0].v=80020002
+Entity.normal.v=80020001
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=80020001
+Entity.type=3010
+Entity.construction=0
+Entity.point[0].v=80020002
+Entity.actNormal.w=1.00000000000000000000
+Entity.actVisible=1
+AddEntity
+
+Entity.h.v=80020002
+Entity.type=2012
+Entity.construction=1
+Entity.actVisible=1
+AddEntity
+
+Constraint.h.v=00000001
+Constraint.type=20
+Constraint.group.v=00000002
+Constraint.workplane.v=80020000
+Constraint.ptA.v=00040002
+Constraint.ptB.v=00050001
+Constraint.other=0
+Constraint.other2=0
+Constraint.reference=0
+AddConstraint
+
+Constraint.h.v=00000002
+Constraint.type=20
+Constraint.group.v=00000002
+Constraint.workplane.v=80020000
+Constraint.ptA.v=00060002
+Constraint.ptB.v=00070001
+Constraint.other=0
+Constraint.other2=0
+Constraint.reference=0
+AddConstraint
+
+Constraint.h.v=00000003
+Constraint.type=54
+Constraint.group.v=00000002
+Constraint.workplane.v=80020000
+Constraint.entityA.v=00040000
+Constraint.entityB.v=00050000
+Constraint.entityC.v=00070000
+Constraint.entityD.v=00060000
+Constraint.other=0
+Constraint.other2=0
+Constraint.reference=0
+AddConstraint
+
index f1e5fce94c4cbc57acd9130fc64c7124ce6add98..e96c709f0101f6312039de58bd4e7eb8fa8b9a0c 100644 (file)
@@ -8,12 +8,12 @@ TEST_CASE(normal_roundtrip) {
 
 TEST_CASE(normal_migrate_from_v20) {
     CHECK_LOAD("normal_v20.slvs");
-    CHECK_SAVE("normal.slvs");
+    CHECK_SAVE("normal_old_version.slvs");
 }
 
 TEST_CASE(normal_migrate_from_v22) {
     CHECK_LOAD("normal_v22.slvs");
-    CHECK_SAVE("normal.slvs");
+    CHECK_SAVE("normal_old_version.slvs");
 }
 
 TEST_CASE(other_roundtrip) {
diff --git a/test/request/image/linked.png b/test/request/image/linked.png
new file mode 100644 (file)
index 0000000..8667e34
Binary files /dev/null and b/test/request/image/linked.png differ
diff --git a/test/request/image/normal.png b/test/request/image/normal.png
new file mode 100644 (file)
index 0000000..a44f72d
Binary files /dev/null and b/test/request/image/normal.png differ
index da0954e0e18b62f10a68ab454097609f43bc1c05..a9507beed3e33de2be891b63206ed593e5ba838c 100644 (file)
@@ -2,13 +2,12 @@
 
 TEST_CASE(normal_roundtrip) {
     CHECK_LOAD("normal.slvs");
-    // Can't render images through cairo for now.
-    // CHECK_RENDER("normal.png");
+    CHECK_RENDER("normal.png");
     CHECK_SAVE("normal.slvs");
 }
 
 TEST_CASE(linked_roundtrip) {
     CHECK_LOAD("linked.slvs");
-    // CHECK_RENDER("linked.png");
+    CHECK_RENDER("linked.png");
     CHECK_SAVE("linked.slvs");
 }