From 4a538913863a7a47da7c05aff02629f9c6cb2b48 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 8 Oct 2024 12:44:08 +0000 Subject: [PATCH] build based on 9769d57 --- stable | 2 +- v0.4 | 2 +- v0.4.83/.documenter-siteinfo.json | 1 + v0.4.83/assets/documenter.js | 889 +++++++++++ v0.4.83/assets/themes/documenter-dark.css | 7 + v0.4.83/assets/themes/documenter-light.css | 9 + v0.4.83/assets/themeswap.js | 84 ++ v0.4.83/assets/warner.js | 52 + .../examples/empty_result_handling/index.html | 1 + v0.4.83/examples/reducibles/index.html | 1 + v0.4.83/examples/transducers/index.html | 1 + v0.4.83/examples/tutorial_missings/index.html | 1 + v0.4.83/examples/tutorial_parallel/index.html | 1 + v0.4.83/examples/words/index.html | 1 + v0.4.83/explanation/ReducePartitionBy.svg | 57 + v0.4.83/explanation/ReduceSplitBy.svg | 89 ++ v0.4.83/explanation/SingleStepConsecutive.svg | 74 + v0.4.83/explanation/WordsXF.svg | 47 + .../comparison_to_iterators/index.html | 64 + v0.4.83/explanation/glossary/index.html | 21 + v0.4.83/explanation/internals/index.html | 190 +++ v0.4.83/explanation/state_machines/index.html | 51 + .../howto/empty_result_handling/index.html | 14 + v0.4.83/howto/reducibles/index.html | 72 + v0.4.83/howto/transducers/index.html | 77 + v0.4.83/howto/useful_patterns/index.html | 159 ++ v0.4.83/index.html | 30 + v0.4.83/interface/index.html | 1 + v0.4.83/manual/index.html | 1 + v0.4.83/parallelism/index.html | 2 + v0.4.83/reference/interface/index.html | 45 + v0.4.83/reference/manual/index.html | 1310 +++++++++++++++++ v0.4.83/search_index.js | 3 + v0.4.83/siteinfo.js | 1 + .../tutorials/tutorial_missings/index.html | 185 +++ .../tutorials/tutorial_parallel/index.html | 147 ++ v0.4.83/tutorials/words/index.html | 106 ++ versions.js | 2 +- 38 files changed, 3797 insertions(+), 3 deletions(-) create mode 100644 v0.4.83/.documenter-siteinfo.json create mode 100644 v0.4.83/assets/documenter.js create mode 100644 v0.4.83/assets/themes/documenter-dark.css create mode 100644 v0.4.83/assets/themes/documenter-light.css create mode 100644 v0.4.83/assets/themeswap.js create mode 100644 v0.4.83/assets/warner.js create mode 100644 v0.4.83/examples/empty_result_handling/index.html create mode 100644 v0.4.83/examples/reducibles/index.html create mode 100644 v0.4.83/examples/transducers/index.html create mode 100644 v0.4.83/examples/tutorial_missings/index.html create mode 100644 v0.4.83/examples/tutorial_parallel/index.html create mode 100644 v0.4.83/examples/words/index.html create mode 100644 v0.4.83/explanation/ReducePartitionBy.svg create mode 100644 v0.4.83/explanation/ReduceSplitBy.svg create mode 100644 v0.4.83/explanation/SingleStepConsecutive.svg create mode 100644 v0.4.83/explanation/WordsXF.svg create mode 100644 v0.4.83/explanation/comparison_to_iterators/index.html create mode 100644 v0.4.83/explanation/glossary/index.html create mode 100644 v0.4.83/explanation/internals/index.html create mode 100644 v0.4.83/explanation/state_machines/index.html create mode 100644 v0.4.83/howto/empty_result_handling/index.html create mode 100644 v0.4.83/howto/reducibles/index.html create mode 100644 v0.4.83/howto/transducers/index.html create mode 100644 v0.4.83/howto/useful_patterns/index.html create mode 100644 v0.4.83/index.html create mode 100644 v0.4.83/interface/index.html create mode 100644 v0.4.83/manual/index.html create mode 100644 v0.4.83/parallelism/index.html create mode 100644 v0.4.83/reference/interface/index.html create mode 100644 v0.4.83/reference/manual/index.html create mode 100644 v0.4.83/search_index.js create mode 100644 v0.4.83/siteinfo.js create mode 100644 v0.4.83/tutorials/tutorial_missings/index.html create mode 100644 v0.4.83/tutorials/tutorial_parallel/index.html create mode 100644 v0.4.83/tutorials/words/index.html diff --git a/stable b/stable index de68a1ec..d8368108 120000 --- a/stable +++ b/stable @@ -1 +1 @@ -v0.4.82 \ No newline at end of file +v0.4.83 \ No newline at end of file diff --git a/v0.4 b/v0.4 index de68a1ec..d8368108 120000 --- a/v0.4 +++ b/v0.4 @@ -1 +1 @@ -v0.4.82 \ No newline at end of file +v0.4.83 \ No newline at end of file diff --git a/v0.4.83/.documenter-siteinfo.json b/v0.4.83/.documenter-siteinfo.json new file mode 100644 index 00000000..3d4996ae --- /dev/null +++ b/v0.4.83/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-08T12:44:03","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/v0.4.83/assets/documenter.js b/v0.4.83/assets/documenter.js new file mode 100644 index 00000000..f5311607 --- /dev/null +++ b/v0.4.83/assets/documenter.js @@ -0,0 +1,889 @@ +// Generated by Documenter.jl +requirejs.config({ + paths: { + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', + 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', + 'minisearch': 'https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min', + 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', + 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', + 'katex': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min', + }, + shim: { + "highlight-julia": { + "deps": [ + "highlight" + ] + }, + "katex-auto-render": { + "deps": [ + "katex" + ] + }, + "headroom-jquery": { + "deps": [ + "jquery", + "headroom" + ] + }, + "highlight-julia-repl": { + "deps": [ + "highlight" + ] + } +} +}); +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'katex', 'katex-auto-render'], function($, katex, renderMathInElement) { +$(document).ready(function() { + renderMathInElement( + document.body, + { + "delimiters": [ + { + "left": "$", + "right": "$", + "display": false + }, + { + "left": "$$", + "right": "$$", + "display": true + }, + { + "left": "\\[", + "right": "\\]", + "display": true + } + ] +} + + ); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'highlight', 'highlight-julia', 'highlight-julia-repl'], function($) { +$(document).ready(function() { + hljs.highlightAll(); +}) + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let timer = 0; +var isExpanded = true; + +$(document).on("click", ".docstring header", function () { + let articleToggleTitle = "Expand docstring"; + + debounce(() => { + if ($(this).siblings("section").is(":visible")) { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + } else { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + articleToggleTitle = "Collapse docstring"; + } + + $(this) + .find(".docstring-article-toggle-button") + .prop("title", articleToggleTitle); + $(this).siblings("section").slideToggle(); + }); +}); + +$(document).on("click", ".docs-article-toggle-button", function () { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + + debounce(() => { + if (isExpanded) { + $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + + isExpanded = false; + + $(".docstring section").slideUp(); + } else { + $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + isExpanded = true; + articleToggleTitle = "Collapse docstring"; + navArticleToggleTitle = "Collapse all docstrings"; + + $(".docstring section").slideDown(); + } + + $(this).prop("title", navArticleToggleTitle); + $(".docstring-article-toggle-button").prop("title", articleToggleTitle); + }); +}); + +function debounce(callback, timeout = 300) { + if (Date.now() - timer > timeout) { + callback(); + } + + clearTimeout(timer); + + timer = Date.now(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require([], function() { +function addCopyButtonCallbacks() { + for (const el of document.getElementsByTagName("pre")) { + const button = document.createElement("button"); + button.classList.add("copy-button", "fa-solid", "fa-copy"); + button.setAttribute("aria-label", "Copy this code block"); + button.setAttribute("title", "Copy"); + + el.appendChild(button); + + const success = function () { + button.classList.add("success", "fa-check"); + button.classList.remove("fa-copy"); + }; + + const failure = function () { + button.classList.add("error", "fa-xmark"); + button.classList.remove("fa-copy"); + }; + + button.addEventListener("click", function () { + copyToClipboard(el.innerText).then(success, failure); + + setTimeout(function () { + button.classList.add("fa-copy"); + button.classList.remove("success", "fa-check", "fa-xmark"); + }, 5000); + }); + } +} + +function copyToClipboard(text) { + // clipboard API is only available in secure contexts + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(text); + } else { + return new Promise(function (resolve, reject) { + try { + const el = document.createElement("textarea"); + el.textContent = text; + el.style.position = "fixed"; + el.style.opacity = 0; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + + resolve(); + } catch (err) { + reject(err); + } finally { + document.body.removeChild(el); + } + }); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", addCopyButtonCallbacks); +} else { + addCopyButtonCallbacks(); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { + +// Manages the top navigation bar (hides it when the user starts scrolling down on the +// mobile). +window.Headroom = Headroom; // work around buggy module loading? +$(document).ready(function () { + $("#documenter .docs-navbar").headroom({ + tolerance: { up: 10, down: 10 }, + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'minisearch'], function($, minisearch) { + +// In general, most search related things will have "search" as a prefix. +// To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +let results = []; +let timer = undefined; + +let data = documenterSearchIndex["docs"].map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; +}); + +// list below is the lunr 2.1.3 list minus the intersect with names(Base) +// (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) +// ideally we'd just filter the original list but it's not available as a variable +const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", +]); + +let index = new minisearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with search results + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not find anything if searching for "add!", only for the entire qualification + tokenize: (string) => string.split(/[\s\-\.]+/), + // options which will be applied during the search + searchOptions: { + boost: { title: 100 }, + fuzzy: 2, + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + tokenize: (string) => string.split(/[\s\-\.]+/), + }, +}); + +index.addAll(data); + +let filters = [...new Set(data.map((x) => x.category))]; +var modal_filters = make_modal_body_filters(filters); +var filter_results = []; + +$(document).on("keyup", ".documenter-search-input", function (event) { + // Adding a debounce to prevent disruptions from super-speed typing! + debounce(() => update_search(filter_results), 300); +}); + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + $(this).removeClass("search-filter-selected"); + } else { + $(this).addClass("search-filter-selected"); + } + + // Adding a debounce to prevent disruptions from crazy clicking! + debounce(() => get_filters(), 300); +}); + +/** + * A debounce function, takes a function and an optional timeout in milliseconds + * + * @function callback + * @param {number} timeout + */ +function debounce(callback, timeout = 300) { + clearTimeout(timer); + timer = setTimeout(callback, timeout); +} + +/** + * Make/Update the search component + * + * @param {string[]} selected_filters + */ +function update_search(selected_filters = []) { + let initial_search_body = ` +
Type something to get started!
+ `; + + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + results = index.search(querystring, { + filter: (result) => { + // Filtering results + if (selected_filters.length === 0) { + return result.score >= 1; + } else { + return ( + result.score >= 1 && selected_filters.includes(result.category) + ); + } + }, + }); + + let search_result_container = ``; + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + results.forEach(function (result) { + if (result.location) { + // Checking for duplication of results for the same page + if (!links.includes(result.location)) { + search_results += make_search_result(result, querystring); + count++; + } + + links.push(result.location); + } + }); + + let result_count = `
${count} result(s)
`; + + search_result_container = ` +
+ ${modal_filters} + ${search_divider} + ${result_count} +
+ ${search_results} +
+
+ `; + } else { + search_result_container = ` +
+ ${modal_filters} + ${search_divider} +
0 result(s)
+
+
No result found!
+ `; + } + + if ($(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").removeClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(search_result_container); + } else { + filter_results = []; + modal_filters = make_modal_body_filters(filters, filter_results); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(initial_search_body); + } +} + +/** + * Make the modal filter html + * + * @param {string[]} filters + * @param {string[]} selected_filters + * @returns string + */ +function make_modal_body_filters(filters, selected_filters = []) { + let str = ``; + + filters.forEach((val) => { + if (selected_filters.includes(val)) { + str += `${val}`; + } else { + str += `${val}`; + } + }); + + let filter_html = ` +
+ Filters: + ${str} +
+ `; + + return filter_html; +} + +/** + * Make the result component given a minisearch result data object and the value of the search input as queryString. + * To view the result object structure, refer: https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ +function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } + + let textindex = new RegExp(`\\b${querystring}\\b`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`\\b${querystring}\\b`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${result.title}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; +} + +/** + * Get selected filters, remake the filter html and lastly update the search modal + */ +function get_filters() { + let ele = $(".search-filters .search-filter-selected").get(); + filter_results = ele.map((x) => $(x).text().toLowerCase()); + modal_filters = make_modal_body_filters(filters, filter_results); + update_search(filter_results); +} + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Modal settings dialog +$(document).ready(function () { + var settings = $("#documenter-settings"); + $("#documenter-settings-button").click(function () { + settings.toggleClass("is-active"); + }); + // Close the dialog if X is clicked + $("#documenter-settings button.delete").click(function () { + settings.removeClass("is-active"); + }); + // Close dialog if ESC is pressed + $(document).keyup(function (e) { + if (e.keyCode == 27) settings.removeClass("is-active"); + }); +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +let search_modal_header = ` + +`; + +let initial_search_body = ` +
Type something to get started!
+`; + +let search_modal_footer = ` + +`; + +$(document.body).append( + ` + + ` +); + +document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); +}); + +document.querySelector(".close-search-modal").addEventListener("click", () => { + closeModal(); +}); + +$(document).on("click", ".search-result-link", function () { + closeModal(); +}); + +document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { + openModal(); + } else if (event.key === "Escape") { + closeModal(); + } + + return false; +}); + +// Functions to open and close a modal +function openModal() { + let searchModal = document.querySelector("#search-modal"); + + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); +} + +function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; + + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); +} + +document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Manages the showing and hiding of the sidebar. +$(document).ready(function () { + var sidebar = $("#documenter > .docs-sidebar"); + var sidebar_button = $("#documenter-sidebar-button"); + sidebar_button.click(function (ev) { + ev.preventDefault(); + sidebar.toggleClass("visible"); + if (sidebar.hasClass("visible")) { + // Makes sure that the current menu item is visible in the sidebar. + $("#documenter .docs-menu a.is-active").focus(); + } + }); + $("#documenter > .docs-main").bind("click", function (ev) { + if ($(ev.target).is(sidebar_button)) { + return; + } + if (sidebar.hasClass("visible")) { + sidebar.removeClass("visible"); + } + }); +}); + +// Resizes the package name / sitename in the sidebar if it is too wide. +// Inspired by: https://github.com/davatron5000/FitText.js +$(document).ready(function () { + e = $("#documenter .docs-autofit"); + function resize() { + var L = parseInt(e.css("max-width"), 10); + var L0 = e.width(); + if (L0 > L) { + var h0 = parseInt(e.css("font-size"), 10); + e.css("font-size", (L * h0) / L0); + // TODO: make sure it survives resizes? + } + } + // call once and then register events + resize(); + $(window).resize(resize); + $(window).on("orientationchange", resize); +}); + +// Scroll the navigation bar to the currently selected menu item +$(document).ready(function () { + var sidebar = $("#documenter .docs-menu").get(0); + var active = $("#documenter .docs-menu .is-active").get(0); + if (typeof active !== "undefined") { + sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// Theme picker setup +$(document).ready(function () { + // onchange callback + $("#documenter-themepicker").change(function themepick_callback(ev) { + var themename = $("#documenter-themepicker option:selected").attr("value"); + if (themename === "auto") { + // set_theme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + window.localStorage.removeItem("documenter-theme"); + } else { + // set_theme(themename); + window.localStorage.setItem("documenter-theme", themename); + } + // We re-use the global function from themeswap.js to actually do the swapping. + set_theme_from_local_storage(); + }); + + // Make sure that the themepicker displays the correct theme when the theme is retrieved + // from localStorage + if (typeof window.localStorage !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if (theme !== null) { + $("#documenter-themepicker option").each(function (i, e) { + e.selected = e.value === theme; + }); + } + } +}); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +// update the version selector with info from the siteinfo.js and ../versions.js files +$(document).ready(function () { + // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the + // siteinfo.js file, we just return immediately and not display the version selector. + if ( + typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === "boolean" && + DOCUMENTER_VERSION_SELECTOR_DISABLED + ) { + return; + } + + var version_selector = $("#documenter .docs-version-selector"); + var version_selector_select = $("#documenter .docs-version-selector select"); + + version_selector_select.change(function (x) { + target_href = version_selector_select + .children("option:selected") + .get(0).value; + window.location.href = target_href; + }); + + // add the current version to the selector based on siteinfo.js, but only if the selector is empty + if ( + typeof DOCUMENTER_CURRENT_VERSION !== "undefined" && + $("#version-selector > option").length == 0 + ) { + var option = $( + "" + ); + version_selector_select.append(option); + } + + if (typeof DOC_VERSIONS !== "undefined") { + var existing_versions = version_selector_select.children("option"); + var existing_versions_texts = existing_versions.map(function (i, x) { + return x.text; + }); + DOC_VERSIONS.forEach(function (each) { + var version_url = documenterBaseURL + "/../" + each + "/"; + var existing_id = $.inArray(each, existing_versions_texts); + // if not already in the version selector, add it as a new option, + // otherwise update the old option with the URL and enable it + if (existing_id == -1) { + var option = $( + "" + ); + version_selector_select.append(option); + } else { + var option = existing_versions[existing_id]; + option.value = version_url; + option.disabled = false; + } + }); + } + + // only show the version selector if the selector has been populated + if (version_selector_select.children("option").length > 0) { + version_selector.toggleClass("visible"); + } +}); + +}) diff --git a/v0.4.83/assets/themes/documenter-dark.css b/v0.4.83/assets/themes/documenter-dark.css new file mode 100644 index 00000000..9f5449f4 --- /dev/null +++ b/v0.4.83/assets/themes/documenter-dark.css @@ -0,0 +1,7 @@ +html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .pagination:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-primary-light{color:#f1f5f9 !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#cddbe9 !important}.has-background-primary-light{background-color:#f1f5f9 !important}.has-text-primary-dark{color:#4d7eb2 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#7198c1 !important}.has-background-primary-dark{background-color:#4d7eb2 !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-link-light{color:#edfdf9 !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c0f6ec !important}.has-background-link-light{background-color:#edfdf9 !important}.has-text-link-dark{color:#15987e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1bc5a4 !important}.has-background-link-dark{background-color:#15987e !important}.has-text-info{color:#024c7d !important}a.has-text-info:hover,a.has-text-info:focus{color:#012d4b !important}.has-background-info{background-color:#024c7d !important}.has-text-info-light{color:#ebf7ff !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#b9e2fe !important}.has-background-info-light{background-color:#ebf7ff !important}.has-text-info-dark{color:#0e9dfb !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#40b1fc !important}.has-background-info-dark{background-color:#0e9dfb !important}.has-text-success{color:#008438 !important}a.has-text-success:hover,a.has-text-success:focus{color:#005122 !important}.has-background-success{background-color:#008438 !important}.has-text-success-light{color:#ebfff3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#b8ffd6 !important}.has-background-success-light{background-color:#ebfff3 !important}.has-text-success-dark{color:#00eb64 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#1fff7e !important}.has-background-success-dark{background-color:#00eb64 !important}.has-text-warning{color:#ad8100 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#7a5b00 !important}.has-background-warning{background-color:#ad8100 !important}.has-text-warning-light{color:#fffaeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#ffedb8 !important}.has-background-warning-light{background-color:#fffaeb !important}.has-text-warning-dark{color:#d19c00 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#ffbf05 !important}.has-background-warning-dark{background-color:#d19c00 !important}.has-text-danger{color:#9e1b0d !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#6f1309 !important}.has-background-danger{background-color:#9e1b0d !important}.has-text-danger-light{color:#fdeeec !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#fac3bd !important}.has-background-danger-light{background-color:#fdeeec !important}.has-text-danger-dark{color:#ec311d !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#f05c4c !important}.has-background-danger-dark{background-color:#ec311d !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--documenter-dark{/*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark optgroup,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:inherit}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1abc9c;text-decoration:none}html.theme--documenter-dark .button.is-ghost:hover,html.theme--documenter-dark .button.is-ghost.is-hovered{color:#1abc9c;text-decoration:underline}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:#ecf0f1;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:#282f2f;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:hover,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-light.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e8eef5;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:active,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-light.is-active,html.theme--documenter-dark .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#dfe8f1;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:#1abc9c;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:hover,html.theme--documenter-dark .button.is-link.is-light.is-hovered{background-color:#e2fbf6;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:active,html.theme--documenter-dark .button.is-link.is-light.is-active{background-color:#d7f9f3;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:#024c7d;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;color:#024c7d}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:hover,html.theme--documenter-dark .button.is-info.is-light.is-hovered{background-color:#def2fe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:active,html.theme--documenter-dark .button.is-info.is-light.is-active{background-color:#d2edfe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:#008438;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;color:#008438}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:hover,html.theme--documenter-dark .button.is-success.is-light.is-hovered{background-color:#deffec;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:active,html.theme--documenter-dark .button.is-success.is-light.is-active{background-color:#d1ffe5;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:#ad8100;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:hover,html.theme--documenter-dark .button.is-warning.is-light.is-hovered{background-color:#fff7de;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:active,html.theme--documenter-dark .button.is-warning.is-light.is-active{background-color:#fff3d1;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:hover,html.theme--documenter-dark .button.is-danger.is-light.is-hovered{background-color:#fce3e0;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:active,html.theme--documenter-dark .button.is-danger.is-light.is-active{background-color:#fcd8d5;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--documenter-dark .button.is-small:not(.is-rounded),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--documenter-dark .button.is-normal{font-size:1rem}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#5e6d6f;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:1rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1.25rem}}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--documenter-dark .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:inherit}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--documenter-dark .content.is-normal{font-size:1rem}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--documenter-dark .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--documenter-dark .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--documenter-dark div.icon-text{display:flex}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--documenter-dark .image.is-fullwidth,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#fff}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .notification.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .notification.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .notification.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .notification.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .notification.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .notification.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .notification.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .notification.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#343c3d}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#024c7d}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #024c7d 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#008438}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#008438}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#008438}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #008438 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ad8100 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #9e1b0d 30%, #343c3d 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#343c3d;background-image:linear-gradient(to right, #fff 30%, #343c3d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-ms-fill{animation-name:none}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table td.is-vcentered,html.theme--documenter-dark .table th.is-vcentered{vertical-align:middle}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#fff}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-primary.is-light:not(body),html.theme--documenter-dark .content kbd.is-primary.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-link.is-light:not(body),html.theme--documenter-dark .content kbd.is-link.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#024c7d;color:#fff}html.theme--documenter-dark .tag.is-info.is-light:not(body),html.theme--documenter-dark .content kbd.is-info.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#008438;color:#fff}html.theme--documenter-dark .tag.is-success.is-light:not(body),html.theme--documenter-dark .content kbd.is-success.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ad8100;color:#fff}html.theme--documenter-dark .tag.is-warning.is-light:not(body),html.theme--documenter-dark .content kbd.is-warning.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .tag.is-danger.is-light:not(body),html.theme--documenter-dark .content kbd.is-danger.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:1rem}html.theme--documenter-dark .title.is-7{font-size:.75rem}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:1rem}html.theme--documenter-dark .subtitle.is-7{font-size:.75rem}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#024c7d}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#008438}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ad8100}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#9e1b0d}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox,html.theme--documenter-dark .radio input[disabled],html.theme--documenter-dark .checkbox input[disabled]{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.5em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#024c7d}html.theme--documenter-dark .select.is-info select{border-color:#024c7d}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#023d64}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#008438}html.theme--documenter-dark .select.is-success select{border-color:#008438}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#006b2d}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#946e00}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#86170b}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff !important;opacity:0.5}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#fff}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(2,76,125,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(0,132,56,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(173,129,0,0.25);color:#fff}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(158,27,13,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--documenter-dark .file.is-normal{font-size:1rem}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#232829;color:#f2f2f2}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#282f2f;color:#fff}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#f2f2f2;display:block;font-size:1rem;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#024c7d}html.theme--documenter-dark .help.is-success{color:#008438}html.theme--documenter-dark .help.is-warning{color:#ad8100}html.theme--documenter-dark .help.is-danger{color:#9e1b0d}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#282f2f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#5e6d6f;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.5em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.5em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-footer:first-child,html.theme--documenter-dark .card-content:first-child,html.theme--documenter-dark .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-footer:last-child,html.theme--documenter-dark .card-content:last-child,html.theme--documenter-dark .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--documenter-dark .media .media .media{padding-top:.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:1rem}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#fff}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f1f5f9}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#4d7eb2}html.theme--documenter-dark .message.is-link{background-color:#edfdf9}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#15987e}html.theme--documenter-dark .message.is-info{background-color:#ebf7ff}html.theme--documenter-dark .message.is-info .message-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#024c7d;color:#0e9dfb}html.theme--documenter-dark .message.is-success{background-color:#ebfff3}html.theme--documenter-dark .message.is-success .message-header{background-color:#008438;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#008438;color:#00eb64}html.theme--documenter-dark .message.is-warning{background-color:#fffaeb}html.theme--documenter-dark .message.is-warning .message-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .message.is-warning .message-body{border-color:#ad8100;color:#d19c00}html.theme--documenter-dark .message.is-danger{background-color:#fdeeec}html.theme--documenter-dark .message.is-danger .message-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#9e1b0d;color:#ec311d}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#fff}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#024c7d;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#008438;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ad8100;color:#fff}}html.theme--documenter-dark .navbar.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#9e1b0d;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:1rem;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.5em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-previous.is-disabled,html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-next.is-disabled,html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-link.is-disabled{background-color:#5e6d6f;border-color:#5e6d6f;box-shadow:none;color:#fff;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}html.theme--documenter-dark .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--documenter-dark .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--documenter-dark .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--documenter-dark .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--documenter-dark .panel.is-light .panel-heading{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-light .panel-tabs a.is-active{border-bottom-color:#ecf0f1}html.theme--documenter-dark .panel.is-light .panel-block.is-active .panel-icon{color:#ecf0f1}html.theme--documenter-dark .panel.is-dark .panel-heading,html.theme--documenter-dark .content kbd.panel .panel-heading{background-color:#282f2f;color:#fff}html.theme--documenter-dark .panel.is-dark .panel-tabs a.is-active,html.theme--documenter-dark .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#282f2f}html.theme--documenter-dark .panel.is-dark .panel-block.is-active .panel-icon,html.theme--documenter-dark .content kbd.panel .panel-block.is-active .panel-icon{color:#282f2f}html.theme--documenter-dark .panel.is-primary .panel-heading,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#375a7f;color:#fff}html.theme--documenter-dark .panel.is-primary .panel-tabs a.is-active,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#375a7f}html.theme--documenter-dark .panel.is-primary .panel-block.is-active .panel-icon,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#375a7f}html.theme--documenter-dark .panel.is-link .panel-heading{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1abc9c}html.theme--documenter-dark .panel.is-link .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel.is-info .panel-heading{background-color:#024c7d;color:#fff}html.theme--documenter-dark .panel.is-info .panel-tabs a.is-active{border-bottom-color:#024c7d}html.theme--documenter-dark .panel.is-info .panel-block.is-active .panel-icon{color:#024c7d}html.theme--documenter-dark .panel.is-success .panel-heading{background-color:#008438;color:#fff}html.theme--documenter-dark .panel.is-success .panel-tabs a.is-active{border-bottom-color:#008438}html.theme--documenter-dark .panel.is-success .panel-block.is-active .panel-icon{color:#008438}html.theme--documenter-dark .panel.is-warning .panel-heading{background-color:#ad8100;color:#fff}html.theme--documenter-dark .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ad8100}html.theme--documenter-dark .panel.is-warning .panel-block.is-active .panel-icon{color:#ad8100}html.theme--documenter-dark .panel.is-danger .panel-heading{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#9e1b0d}html.theme--documenter-dark .panel.is-danger .panel-block.is-active .panel-icon{color:#9e1b0d}html.theme--documenter-dark .panel-tabs:not(:last-child),html.theme--documenter-dark .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--documenter-dark .panel-heading{background-color:#343c3d;border-radius:8px 8px 0 0;color:#f2f2f2;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none;width:unset}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none;width:unset}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none;width:unset}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none;width:unset}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none;width:unset}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none;width:unset}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.33333337%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.66666674%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.33333337%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.66666674%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.33333337%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.66666674%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.33333337%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.66666674%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{color:#ecf0f1 !important;opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#fff}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#fff}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{color:#282f2f !important;opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#375a7f !important;opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{color:#1abc9c !important;opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#024c7d}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{color:#024c7d !important;opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#024c7d}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#008438}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{color:#008438 !important;opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#008438}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:#fff}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#ad8100}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{color:#ad8100 !important;opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ad8100}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#9e1b0d}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{color:#9e1b0d !important;opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#9e1b0d}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-body{padding:3rem 3rem}}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section{padding:3rem 3rem}html.theme--documenter-dark .section.is-medium{padding:9rem 4.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 6rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#0363a3}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#024c7d;box-shadow:0 0 0 2px rgba(2,76,125,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#00aa48}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#008438;box-shadow:0 0 0 2px rgba(0,132,56,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#d39e00}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#ad8100;box-shadow:0 0 0 2px rgba(173,129,0,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#c12110}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#9e1b0d;box-shadow:0 0 0 2px rgba(158,27,13,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:1px;border-color:#5e6d6f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#5e6d6f}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:#5e6d6f;color:#fff}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#024c7d}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#008438}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:#008438;color:#fff}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#ad8100}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#9e1b0d}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#137886}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:#137886;color:#fff}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#fff;background-color:#5e6d6f;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark details.admonition.is-details>.admonition-header{list-style:none}html.theme--documenter-dark details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--documenter-dark details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #5e6d6f;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f;overflow:auto}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid #9e1b0d;padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:1px solid #5e6d6f}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--documenter-dark #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--documenter-dark .search-min-width-50{min-width:50%}html.theme--documenter-dark .search-min-height-100{min-height:100%}html.theme--documenter-dark .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--documenter-dark .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--documenter-dark .search-filter:hover,html.theme--documenter-dark .search-filter:focus{color:#333}html.theme--documenter-dark .search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}html.theme--documenter-dark .search-filter-selected:hover,html.theme--documenter-dark .search-filter-selected:focus{color:#f5f5f5}html.theme--documenter-dark .search-result-highlight{background-color:#ffdd57;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .search-result-title{width:85%;color:#f5f5f5}html.theme--documenter-dark .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem}html.theme--documenter-dark .gap-8{gap:2rem}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333 !important;background-color:#f1f5f9 !important}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:whitesmoke;background-color:#33415580;border-radius:0.6rem}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem} diff --git a/v0.4.83/assets/themes/documenter-light.css b/v0.4.83/assets/themes/documenter-light.css new file mode 100644 index 00000000..2f168c77 --- /dev/null +++ b/v0.4.83/assets/themes/documenter-light.css @@ -0,0 +1,9 @@ +.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.pagination:not(:last-child),.message:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-primary-light{color:#eef8fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c3e6f4 !important}.has-background-primary-light{background-color:#eef8fc !important}.has-text-primary-dark{color:#1a6d8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#228eb9 !important}.has-background-primary-dark{background-color:#1a6d8e !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-link-light{color:#eff3fb !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c6d6f1 !important}.has-background-link-light{background-color:#eff3fb !important}.has-text-link-dark{color:#3169c4 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#5485d4 !important}.has-background-link-dark{background-color:#3169c4 !important}.has-text-info{color:#209cee !important}a.has-text-info:hover,a.has-text-info:focus{color:#1081cb !important}.has-background-info{background-color:#209cee !important}.has-text-info-light{color:#ecf7fe !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#bde2fa !important}.has-background-info-light{background-color:#ecf7fe !important}.has-text-info-dark{color:#0e72b4 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#1190e3 !important}.has-background-info-dark{background-color:#0e72b4 !important}.has-text-success{color:#22c35b !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a9847 !important}.has-background-success{background-color:#22c35b !important}.has-text-success-light{color:#eefcf3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c2f4d4 !important}.has-background-success-light{background-color:#eefcf3 !important}.has-text-success-dark{color:#198f43 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#21bb57 !important}.has-background-success-dark{background-color:#198f43 !important}.has-text-warning{color:#ffdd57 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#ffd324 !important}.has-background-warning{background-color:#ffdd57 !important}.has-text-warning-light{color:#fffbeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fff1b8 !important}.has-background-warning-light{background-color:#fffbeb !important}.has-text-warning-dark{color:#947600 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#c79f00 !important}.has-background-warning-dark{background-color:#947600 !important}.has-text-danger{color:#da0b00 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a70800 !important}.has-background-danger{background-color:#da0b00 !important}.has-text-danger-light{color:#ffeceb !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#ffbbb8 !important}.has-background-danger-light{background-color:#ffeceb !important}.has-text-danger-dark{color:#f50c00 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#ff3429 !important}.has-background-danger-dark{background-color:#f50c00 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#222}@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:#bbb;color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#222;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#2e63b8;text-decoration:none}.button.is-ghost:hover,.button.is-ghost.is-hovered{color:#2e63b8;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#fff}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:#363636;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light,.docstring>section>a.button.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.button.is-primary.is-light:hover,.docstring>section>a.button.is-light.docs-sourcelink:hover,.button.is-primary.is-light.is-hovered,.docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e3f3fa;border-color:transparent;color:#1a6d8e}.button.is-primary.is-light:active,.docstring>section>a.button.is-light.docs-sourcelink:active,.button.is-primary.is-light.is-active,.docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d8eff8;border-color:transparent;color:#1a6d8e}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:#2e63b8;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff3fb;color:#3169c4}.button.is-link.is-light:hover,.button.is-link.is-light.is-hovered{background-color:#e4ecf8;border-color:transparent;color:#3169c4}.button.is-link.is-light:active,.button.is-link.is-light.is-active{background-color:#dae5f6;border-color:transparent;color:#3169c4}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#1497ed;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#1190e3;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#209cee;border-color:#209cee;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#209cee}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#209cee;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.button.is-info.is-light:hover,.button.is-info.is-light.is-hovered{background-color:#e0f1fd;border-color:transparent;color:#0e72b4}.button.is-info.is-light:active,.button.is-info.is-light.is-active{background-color:#d4ecfc;border-color:transparent;color:#0e72b4}.button.is-success{background-color:#22c35b;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#20b856;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#1ead51;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#22c35b;border-color:#22c35b;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#22c35b}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#22c35b}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;color:#22c35b}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#22c35b;border-color:#22c35b;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;box-shadow:none;color:#22c35b}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#22c35b}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#eefcf3;color:#198f43}.button.is-success.is-light:hover,.button.is-success.is-light.is-hovered{background-color:#e3faeb;border-color:transparent;color:#198f43}.button.is-success.is-light:active,.button.is-success.is-light.is-active{background-color:#d8f8e3;border-color:transparent;color:#198f43}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffdd57;border-color:#ffdd57;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-warning.is-light{background-color:#fffbeb;color:#947600}.button.is-warning.is-light:hover,.button.is-warning.is-light.is-hovered{background-color:#fff8de;border-color:transparent;color:#947600}.button.is-warning.is-light:active,.button.is-warning.is-light.is-active{background-color:#fff6d1;border-color:transparent;color:#947600}.button.is-danger{background-color:#da0b00;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#cd0a00;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#c10a00;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#da0b00;border-color:#da0b00;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#da0b00}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;color:#da0b00}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#da0b00;border-color:#da0b00;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;box-shadow:none;color:#da0b00}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.button.is-danger.is-light:hover,.button.is-danger.is-light.is-hovered{background-color:#ffe0de;border-color:transparent;color:#f50c00}.button.is-danger.is-light:active,.button.is-danger.is-light.is-active{background-color:#ffd3d1;border-color:transparent;color:#f50c00}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}.button.is-small:not(.is-rounded),#documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.65625rem}.button.is-responsive.is-medium{font-size:.75rem}.button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.75rem}.button.is-responsive.is-medium{font-size:1rem}.button.is-responsive.is-large{font-size:1.25rem}}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){.container{max-width:992px}}@media screen and (max-width: 1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}.image.is-fullwidth,#documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{right:.5rem;position:absolute;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#fff}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-primary.is-light,.docstring>section>a.notification.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-link.is-light{background-color:#eff3fb;color:#3169c4}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.notification.is-success{background-color:#22c35b;color:#fff}.notification.is-success.is-light{background-color:#eefcf3;color:#198f43}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.notification.is-warning.is-light{background-color:#fffbeb;color:#947600}.notification.is-danger{background-color:#da0b00;color:#fff}.notification.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #ededed 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #ededed 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #209cee 30%, #ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#22c35b}.progress.is-success::-moz-progress-bar{background-color:#22c35b}.progress.is-success::-ms-fill{background-color:#22c35b}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #22c35b 30%, #ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ffdd57 30%, #ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#da0b00}.progress.is-danger::-moz-progress-bar{background-color:#da0b00}.progress.is-danger::-ms-fill{background-color:#da0b00}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #da0b00 30%, #ededed 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right, #222 30%, #ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#222}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#22c35b;border-color:#22c35b;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.table td.is-danger,.table th.is-danger{background-color:#da0b00;border-color:#da0b00;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#fff}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-primary.is-light:not(body),.content kbd.is-primary.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#eef8fc;color:#1a6d8e}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-link.is-light:not(body),.content kbd.is-link.is-light:not(body),.docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#eff3fb;color:#3169c4}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#209cee;color:#fff}.tag.is-info.is-light:not(body),.content kbd.is-info.is-light:not(body),.docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ecf7fe;color:#0e72b4}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#22c35b;color:#fff}.tag.is-success.is-light:not(body),.content kbd.is-success.is-light:not(body),.docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#eefcf3;color:#198f43}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ffdd57;color:rgba(0,0,0,0.7)}.tag.is-warning.is-light:not(body),.content kbd.is-warning.is-light:not(body),.docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffbeb;color:#947600}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#da0b00;color:#fff}.tag.is-danger.is-light:not(body),.content kbd.is-danger.is-light:not(body),.docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#ffeceb;color:#f50c00}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#222;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#222;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#222;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#222}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#707070}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#707070}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#707070}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#707070}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#209cee}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#22c35b}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ffdd57}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#da0b00}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#222}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox,.radio input[disabled],.checkbox input[disabled]{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#222}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#209cee}.select.is-info select{border-color:#209cee}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#1190e3}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.select.is-success:not(:hover)::after{border-color:#22c35b}.select.is-success select{border-color:#22c35b}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#1ead51}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.select.is-warning:not(:hover)::after{border-color:#ffdd57}.select.is-warning select{border-color:#ffdd57}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#ffd83e}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.select.is-danger:not(:hover)::after{border-color:#da0b00}.select.is-danger select{border-color:#da0b00}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#c10a00}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b !important;opacity:0.5}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#fff}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#1497ed;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(32,156,238,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#1190e3;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#22c35b;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#20b856;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(34,195,91,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#1ead51;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,221,87,0.25);color:rgba(0,0,0,0.7)}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-danger .file-cta{background-color:#da0b00;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#cd0a00;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(218,11,0,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#c10a00;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#222}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#222}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#222}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#222;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#209cee}.help.is-success{color:#22c35b}.help.is-warning{color:#ffdd57}.help.is-danger{color:#da0b00}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#222}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:#bbb;color:#222;max-width:100%;position:relative}.card-footer:first-child,.card-content:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-footer:last-child,.card-content:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:#bbb;padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#222;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#eef8fc}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1a6d8e}.message.is-link{background-color:#eff3fb}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#3169c4}.message.is-info{background-color:#ecf7fe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#0e72b4}.message.is-success{background-color:#eefcf3}.message.is-success .message-header{background-color:#22c35b;color:#fff}.message.is-success .message-body{border-color:#22c35b;color:#198f43}.message.is-warning{background-color:#fffbeb}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#947600}.message.is-danger{background-color:#ffeceb}.message.is-danger .message-header{background-color:#da0b00;color:#fff}.message.is-danger .message-body{border-color:#da0b00;color:#f50c00}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#fff}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#fff}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#22c35b;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#22c35b;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,0.7)}}.navbar.is-danger{background-color:#da0b00;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#da0b00;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#222;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#222;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#222;min-width:2.5em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-previous.is-disabled,.pagination-next[disabled],.pagination-next.is-disabled,.pagination-link[disabled],.pagination-link.is-disabled{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:#bbb;font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading,.content kbd.panel .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active,.content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon,.content kbd.panel .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading,.docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#4eb5de;color:#fff}.panel.is-primary .panel-tabs a.is-active,.docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#4eb5de}.panel.is-primary .panel-block.is-active .panel-icon,.docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#4eb5de}.panel.is-link .panel-heading{background-color:#2e63b8;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#2e63b8}.panel.is-link .panel-block.is-active .panel-icon{color:#2e63b8}.panel.is-info .panel-heading{background-color:#209cee;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#209cee}.panel.is-info .panel-block.is-active .panel-icon{color:#209cee}.panel.is-success .panel-heading{background-color:#22c35b;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#22c35b}.panel.is-success .panel-block.is-active .panel-icon{color:#22c35b}.panel.is-warning .panel-heading{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffdd57}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffdd57}.panel.is-danger .panel-heading{background-color:#da0b00;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#da0b00}.panel.is-danger .panel-block.is-active .panel-icon{color:#da0b00}.panel-tabs:not(:last-child),.panel-block:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#222;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>.column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>.column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>.column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>.column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.33333337%}.column.is-offset-1-mobile{margin-left:8.33333337%}.column.is-2-mobile{flex:none;width:16.66666674%}.column.is-offset-2-mobile{margin-left:16.66666674%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333337%}.column.is-offset-4-mobile{margin-left:33.33333337%}.column.is-5-mobile{flex:none;width:41.66666674%}.column.is-offset-5-mobile{margin-left:41.66666674%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333337%}.column.is-offset-7-mobile{margin-left:58.33333337%}.column.is-8-mobile{flex:none;width:66.66666674%}.column.is-offset-8-mobile{margin-left:66.66666674%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333337%}.column.is-offset-10-mobile{margin-left:83.33333337%}.column.is-11-mobile{flex:none;width:91.66666674%}.column.is-offset-11-mobile{margin-left:91.66666674%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333337%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333337%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66666674%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66666674%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333337%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333337%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66666674%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66666674%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333337%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333337%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66666674%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66666674%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333337%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333337%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66666674%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66666674%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.33333337%}.column.is-offset-1-touch{margin-left:8.33333337%}.column.is-2-touch{flex:none;width:16.66666674%}.column.is-offset-2-touch{margin-left:16.66666674%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333337%}.column.is-offset-4-touch{margin-left:33.33333337%}.column.is-5-touch{flex:none;width:41.66666674%}.column.is-offset-5-touch{margin-left:41.66666674%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333337%}.column.is-offset-7-touch{margin-left:58.33333337%}.column.is-8-touch{flex:none;width:66.66666674%}.column.is-offset-8-touch{margin-left:66.66666674%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333337%}.column.is-offset-10-touch{margin-left:83.33333337%}.column.is-11-touch{flex:none;width:91.66666674%}.column.is-offset-11-touch{margin-left:91.66666674%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.33333337%}.column.is-offset-1-desktop{margin-left:8.33333337%}.column.is-2-desktop{flex:none;width:16.66666674%}.column.is-offset-2-desktop{margin-left:16.66666674%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333337%}.column.is-offset-4-desktop{margin-left:33.33333337%}.column.is-5-desktop{flex:none;width:41.66666674%}.column.is-offset-5-desktop{margin-left:41.66666674%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333337%}.column.is-offset-7-desktop{margin-left:58.33333337%}.column.is-8-desktop{flex:none;width:66.66666674%}.column.is-offset-8-desktop{margin-left:66.66666674%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333337%}.column.is-offset-10-desktop{margin-left:83.33333337%}.column.is-11-desktop{flex:none;width:91.66666674%}.column.is-offset-11-desktop{margin-left:91.66666674%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.33333337%}.column.is-offset-1-widescreen{margin-left:8.33333337%}.column.is-2-widescreen{flex:none;width:16.66666674%}.column.is-offset-2-widescreen{margin-left:16.66666674%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333337%}.column.is-offset-4-widescreen{margin-left:33.33333337%}.column.is-5-widescreen{flex:none;width:41.66666674%}.column.is-offset-5-widescreen{margin-left:41.66666674%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333337%}.column.is-offset-7-widescreen{margin-left:58.33333337%}.column.is-8-widescreen{flex:none;width:66.66666674%}.column.is-offset-8-widescreen{margin-left:66.66666674%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333337%}.column.is-offset-10-widescreen{margin-left:83.33333337%}.column.is-11-widescreen{flex:none;width:91.66666674%}.column.is-offset-11-widescreen{margin-left:91.66666674%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.33333337%}.column.is-offset-1-fullhd{margin-left:8.33333337%}.column.is-2-fullhd{flex:none;width:16.66666674%}.column.is-offset-2-fullhd{margin-left:16.66666674%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333337%}.column.is-offset-4-fullhd{margin-left:33.33333337%}.column.is-5-fullhd{flex:none;width:41.66666674%}.column.is-offset-5-fullhd{margin-left:41.66666674%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333337%}.column.is-offset-7-fullhd{margin-left:58.33333337%}.column.is-8-fullhd{flex:none;width:66.66666674%}.column.is-offset-8-fullhd{margin-left:66.66666674%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333337%}.column.is-offset-10-fullhd{margin-left:83.33333337%}.column.is-11-fullhd{flex:none;width:91.66666674%}.column.is-offset-11-fullhd{margin-left:91.66666674%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333337%}.tile.is-2{flex:none;width:16.66666674%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333337%}.tile.is-5{flex:none;width:41.66666674%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333337%}.tile.is-8{flex:none;width:66.66666674%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333337%}.tile.is-11{flex:none;width:91.66666674%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,0.7)}.hero.is-light .subtitle{color:rgba(0,0,0,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#fff}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#fff}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#fff;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{color:#363636 !important;opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#4eb5de !important;opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#2e63b8 !important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#1190e3;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#209cee !important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}}.hero.is-success{background-color:#22c35b;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#22c35b}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#1ead51;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#22c35b !important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#22c35b}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffdd57 !important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}}.hero.is-danger{background-color:#da0b00;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#da0b00}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#c10a00;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#da0b00 !important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#da0b00}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#b5b5b5;border-style:solid;border-width:1px;border-color:#363636;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#b5b5b5;border-color:#363636}.admonition.is-default>.admonition-header{background-color:#363636;color:#fff}.admonition.is-default>.admonition-body{color:#fff}.admonition.is-info{background-color:#def0fc;border-color:#209cee}.admonition.is-info>.admonition-header{background-color:#209cee;color:#fff}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#bdf4d1;border-color:#22c35b}.admonition.is-success>.admonition-header{background-color:#22c35b;color:#fff}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#fff3c5;border-color:#ffdd57}.admonition.is-warning>.admonition-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#ffaba7;border-color:#da0b00}.admonition.is-danger>.admonition-header{background-color:#da0b00;color:#fff}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#bdeff5;border-color:#1db5c9}.admonition.is-compat>.admonition-header{background-color:#1db5c9;color:#fff}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#fff;background-color:#363636;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}details.admonition.is-details>.admonition-header{list-style:none}details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #dbdbdb;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb;overflow:auto}.docstring>header code{background-color:transparent}.docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#ffaba7;color:rgba(0,0,0,0.7);border-bottom:3px solid #da0b00;padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:1px solid #dbdbdb}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1;overflow-x:hidden}#documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}#documenter .docs-sidebar #documenter-search-query{color:#707070;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(0,0,0,0.6);box-shadow:0 2px 0 1px rgba(0,0,0,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}.search-min-width-50{min-width:50%}.search-min-height-100{min-height:100%}.search-modal-card-body{max-height:calc(100vh - 15rem)}.search-result-link{border-radius:0.7em;transition:all 300ms}.search-result-link:hover,.search-result-link:focus{background-color:rgba(0,128,128,0.1)}.search-result-link .property-search-result-badge,.search-result-link .search-filter{transition:all 300ms}.property-search-result-badge,.search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}.search-result-link:hover .property-search-result-badge,.search-result-link:hover .search-filter,.search-result-link:focus .property-search-result-badge,.search-result-link:focus .search-filter{color:#f1f5f9;background-color:#333}.search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}.search-filter:hover,.search-filter:focus{color:#333}.search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}.search-filter-selected:hover,.search-filter-selected:focus{color:#f5f5f5}.search-result-highlight{background-color:#ffdd57;color:black}.search-divider{border-bottom:1px solid #dbdbdb}.search-result-title{width:85%;color:#333}.search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}#search-modal .modal-card-body::-webkit-scrollbar,#search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}#search-modal .modal-card-body::-webkit-scrollbar-thumb,#search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}#search-modal .modal-card-body::-webkit-scrollbar-track,#search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}.w-100{width:100%}.gap-2{gap:0.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! + Theme: Default + Description: Original highlight.js style + Author: (c) Ivan Sagalaev + Maintainer: @highlightjs/core-team + Website: https://highlightjs.org/ + License: see project LICENSE + Touched: 2021 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#F3F3F3;color:#444}.hljs-comment{color:#697070}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#ab5656}.hljs-literal{color:#695}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}.gap-4{gap:1rem} diff --git a/v0.4.83/assets/themeswap.js b/v0.4.83/assets/themeswap.js new file mode 100644 index 00000000..9f5eebe6 --- /dev/null +++ b/v0.4.83/assets/themeswap.js @@ -0,0 +1,84 @@ +// Small function to quickly swap out themes. Gets put into the tag.. +function set_theme_from_local_storage() { + // Initialize the theme to null, which means default + var theme = null; + // If the browser supports the localstorage and is not disabled then try to get the + // documenter theme + if (window.localStorage != null) { + // Get the user-picked theme from localStorage. May be `null`, which means the default + // theme. + theme = window.localStorage.getItem("documenter-theme"); + } + // Check if the users preference is for dark color scheme + var darkPreference = + window.matchMedia("(prefers-color-scheme: dark)").matches === true; + // Initialize a few variables for the loop: + // + // - active: will contain the index of the theme that should be active. Note that there + // is no guarantee that localStorage contains sane values. If `active` stays `null` + // we either could not find the theme or it is the default (primary) theme anyway. + // Either way, we then need to stick to the primary theme. + // + // - disabled: style sheets that should be disabled (i.e. all the theme style sheets + // that are not the currently active theme) + var active = null; + var disabled = []; + var primaryLightTheme = null; + var primaryDarkTheme = null; + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // To distinguish the default (primary) theme, it needs to have the data-theme-primary + // attribute set. + if (ss.ownerNode.getAttribute("data-theme-primary") !== null) { + primaryLightTheme = themename; + } + // Check if the theme is primary dark theme so that we could store its name in darkTheme + if (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null) { + primaryDarkTheme = themename; + } + // If we find a matching theme (and it's not the default), we'll set active to non-null + if (themename === theme) active = i; + // Store the style sheets of inactive themes so that we could disable them + if (themename !== theme) disabled.push(ss); + } + var activeTheme = null; + if (active !== null) { + // If we did find an active theme, we'll (1) add the theme--$(theme) class to + document.getElementsByTagName("html")[0].className = "theme--" + theme; + activeTheme = theme; + } else { + // If we did _not_ find an active theme, then we need to fall back to the primary theme + // which can either be dark or light, depending on the user's OS preference. + var activeTheme = darkPreference ? primaryDarkTheme : primaryLightTheme; + // In case it somehow happens that the relevant primary theme was not found in the + // preceding loop, we abort without doing anything. + if (activeTheme === null) { + console.error("Unable to determine primary theme."); + return; + } + // When switching to the primary light theme, then we must not have a class name + // for the tag. That's only for non-primary or the primary dark theme. + if (darkPreference) { + document.getElementsByTagName("html")[0].className = + "theme--" + activeTheme; + } else { + document.getElementsByTagName("html")[0].className = ""; + } + } + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // we'll disable all the stylesheets, except for the active one + ss.disabled = !(themename == activeTheme); + } +} +set_theme_from_local_storage(); diff --git a/v0.4.83/assets/warner.js b/v0.4.83/assets/warner.js new file mode 100644 index 00000000..3f6f5d00 --- /dev/null +++ b/v0.4.83/assets/warner.js @@ -0,0 +1,52 @@ +function maybeAddWarning() { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return; + } + + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return; + } + + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return; + } + + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement("meta"); + meta.name = "robots"; + meta.content = "noindex"; + + document.getElementsByTagName("head")[0].appendChild(meta); + } + + const div = document.createElement("div"); + div.classList.add("outdated-warning-overlay"); + const closer = document.createElement("button"); + closer.classList.add("outdated-warning-closer", "delete"); + closer.addEventListener("click", function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE; + div.innerHTML = + 'This documentation is not for the latest stable release, but for either the development version or an older release.
Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", maybeAddWarning); +} else { + maybeAddWarning(); +} diff --git a/v0.4.83/examples/empty_result_handling/index.html b/v0.4.83/examples/empty_result_handling/index.html new file mode 100644 index 00000000..26ebf5eb --- /dev/null +++ b/v0.4.83/examples/empty_result_handling/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/examples/reducibles/index.html b/v0.4.83/examples/reducibles/index.html new file mode 100644 index 00000000..6979695a --- /dev/null +++ b/v0.4.83/examples/reducibles/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/examples/transducers/index.html b/v0.4.83/examples/transducers/index.html new file mode 100644 index 00000000..4f50f240 --- /dev/null +++ b/v0.4.83/examples/transducers/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/examples/tutorial_missings/index.html b/v0.4.83/examples/tutorial_missings/index.html new file mode 100644 index 00000000..7eb80e18 --- /dev/null +++ b/v0.4.83/examples/tutorial_missings/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/examples/tutorial_parallel/index.html b/v0.4.83/examples/tutorial_parallel/index.html new file mode 100644 index 00000000..34422494 --- /dev/null +++ b/v0.4.83/examples/tutorial_parallel/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/examples/words/index.html b/v0.4.83/examples/words/index.html new file mode 100644 index 00000000..17a0b3f3 --- /dev/null +++ b/v0.4.83/examples/words/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/explanation/ReducePartitionBy.svg b/v0.4.83/explanation/ReducePartitionBy.svg new file mode 100644 index 00000000..c8a78214 --- /dev/null +++ b/v0.4.83/explanation/ReducePartitionBy.svg @@ -0,0 +1,57 @@ + + + + + + +ReducePartitionBy + + + +Vacant + + +Vacant + + + +Vacant->Vacant + + +R? + + + +Unseen + +Unseen + + + +Chunk + +Chunk + + + +Unseen->Chunk + + + + + +Chunk->Vacant + + + + + +Chunk->Chunk + + + + + diff --git a/v0.4.83/explanation/ReduceSplitBy.svg b/v0.4.83/explanation/ReduceSplitBy.svg new file mode 100644 index 00000000..86c9dc62 --- /dev/null +++ b/v0.4.83/explanation/ReduceSplitBy.svg @@ -0,0 +1,89 @@ + + + + + + +ReduceSplitBy + + + +PreVacant + + +PreVacant + + + +PreVacant->PreVacant + + +R + + + +Vacant + + +Vacant + + + +PreVacant:se->Vacant:sw + + + + + +Vacant->PreVacant + + +R + + + +Vacant->Vacant + + + + + +PreChunk + +PreChunk + + + +PreChunk->PreVacant + + + + + +Chunk + +Chunk + + + +PreChunk->Chunk + + + + + +Chunk->PreVacant + + + + + +Chunk->Chunk + + + + + diff --git a/v0.4.83/explanation/SingleStepConsecutive.svg b/v0.4.83/explanation/SingleStepConsecutive.svg new file mode 100644 index 00000000..b9706c3b --- /dev/null +++ b/v0.4.83/explanation/SingleStepConsecutive.svg @@ -0,0 +1,74 @@ + + + + + + +SingleStepConsecutive + + + +Buffer{N-1} + + +Buffer{N-1} + + + +Buffer{N-1}->Buffer{N-1} + + +NTuple{N,Any} + + + + ... + ... + + + +Buffer{N-2} + +Buffer{N-2} + + + + ... ->Buffer{N-2} + + + + + +Buffer{0} + +Buffer{0} + + + +Buffer{1} + +Buffer{1} + + + +Buffer{0}->Buffer{1} + + + + + +Buffer{1}-> ... + + + + + +Buffer{N-2}->Buffer{N-1} + + + + + diff --git a/v0.4.83/explanation/WordsXF.svg b/v0.4.83/explanation/WordsXF.svg new file mode 100644 index 00000000..0e92f1e6 --- /dev/null +++ b/v0.4.83/explanation/WordsXF.svg @@ -0,0 +1,47 @@ + + + + + + +WordsXF + + + +Vacant + + +Vacant + + + +Vacant->Vacant + + +Union{Nothing,String} + + + +Chunk + +Chunk + + + +Chunk->Vacant + + +Nothing + + + +Chunk->Chunk + + +Nothing + + + diff --git a/v0.4.83/explanation/comparison_to_iterators/index.html b/v0.4.83/explanation/comparison_to_iterators/index.html new file mode 100644 index 00000000..00bd5393 --- /dev/null +++ b/v0.4.83/explanation/comparison_to_iterators/index.html @@ -0,0 +1,64 @@ + +Comparison to iterators · Transducers.jl

Comparison to iterators

How foldl is used illustrates the difference between iterators and transducers. Consider a transducer

julia> using Transducers
+
+julia> xf = opcompose(Filter(iseven), Map(x -> 2x));

which works as

julia> collect(xf, 1:6)
+3-element Vector{Int64}:
+  4
+  8
+ 12
+
+julia> foldl(+, xf, 1:6)  # 4 + 8 + 12
+24

Implementation of the above computation in iterator would be:

f(x) = 2x
+imap = Base.Iterators.Generator  # like `map`, but returns an iterator
+mapfoldl(f, +, filter(iseven, input), init=0)
+foldl(+, imap(f, filter(iseven, input)))  # equivalent
+#        ______________________________
+#        composition occurs at input part

Compare it to how transducers are used:

foldl(+, opcompose(Filter(iseven), Map(f)), input, init=0)
+#        _________________________________
+#        composition occurs at computation part

Although this is just a syntactic difference, it is reflected in the actual code generated by those two frameworks. The code for iterator would be lowered to:

function map_filter_iterators(xs, init)
+    ret = iterate(xs)
+    ret === nothing && return init
+    acc = init
+    @goto filter
+    local state, x
+    while true
+        while true                                    # input
+            ret = iterate(xs, state)                  #
+            ret === nothing && return acc             #
+            @label filter                             #
+            x, state = ret                            #
+            iseven(x) && break             # filter   :
+        end                                #          :
+        y = 2x              # imap         :          :
+        acc += y    # +     :              :          :
+    end             # :     :              :          :
+    #                 + <-- imap <-------- filter <-- input
+end

Notice that the iteration of input is the inner most block, followed by filter, imap, and then finally +. Iterators are described as pull-based; an outer iterator (say imap) has to "pull" an item from the inner iterator (filter in above example). It is reflected in the lowered code above.

On the other hand, the code using transducers is lowered to:

function map_filter_transducers(xs, init)
+    acc = init
+    #              input -> Filter --> Map --> +
+    for x in xs  # input    :          :       :
+        if iseven(x)  #     Filter     :       :
+            y = 2x    #                Map     :
+            acc += y  #                        +
+        end
+    end
+    return acc
+end
+
+xs = [6, 8, 1, 4, 5, 6, 6, 7, 9, 9, 7, 8, 6, 8, 2, 5, 2, 4, 3, 7]
+@assert map_filter_iterators(xs, 0) == map_filter_transducers(xs, 0)

Notice that the iteration of input is at the outer most block while + is in the inner most block. Transducers passed to foldl appears in the block between them in the order they are composed. An outer transducer (say Filter) "pushes" arbitrary number of items to the inner transducer (Map in above example). Note that Filter can choose to not push an item (i.e., push zero item) when the predicate returns false. This push-based nature of the transducers allows the generation of very natural and efficient code. To put it another way, the transducers and transducible processes own the loop.

As a consequence, computations requiring to expand an item into a sequence can be processed efficiently. Consider the following example:

julia> xf = opcompose(Map(x -> 1:x), Filter(iseven ∘ sum), Cat())
+       foldl(*, xf, 1:10)
+29262643200

This is lowered to a nested for loops:

function map_filter_cat_transducers(xs, init)
+    acc = init
+    for x in xs
+        y1 = 1:x                # Map
+        if iseven(sum(y1))      # Filter
+            for y2 in y1        # Cat
+                acc *= y2       # *
+            end
+        end
+    end
+    return acc
+end
+
+@assert foldl(*, xf, 1:10) == map_filter_cat_transducers(1:10, 1)

It is not straightforward to implement an iterator like Cat that can output more than one items at a time. Such an iterator has to track the state of the inner (y1 in above) and outer (xs in above) iterators and conditionally invoke the outer iterator once the inner iterator terminates. This generates a complicated code and the compiler would have hard time optimizing it.

diff --git a/v0.4.83/explanation/glossary/index.html b/v0.4.83/explanation/glossary/index.html new file mode 100644 index 00000000..09cce3ab --- /dev/null +++ b/v0.4.83/explanation/glossary/index.html @@ -0,0 +1,21 @@ + +Glossary · Transducers.jl

Glossary

foldl(step, xf, input, init=...)
+#  |   |    |     |
+#  |   |    |     `-- reducible
+#  |   |    |
+#  |   |    `-- transducer
+#  |   |
+#  |   `-- "bottom" (inner most) reducing function
+#  |
+#  `-- transducible process

Reducing step function

Reducing function or Reducing step (function): A reducing function combines result-so-far with the input. It in a narrow sense is a "callable" op of the signature op(::X, ::Y) :: X (or op(::X, ::X) :: X in case for foldxt) or schematically:

\[(\text{result-so-far}, \text{input}) \mapsto \text{result-so-far}\]

It is the function that can be passed to the classic (non-Transducers.jl) Base.foldl or Base.reduce. It is sometimes referred to as a step or op. In Transducers.jl, next(rf, ::X, ::Y) :: X is used instead of a "bare" callable. Furthermore, a reducing function in a loose sense also includes other interfaces such as start(rf, ::X) and complete(rf, ::X).

Transducer

A transducer in Transducers.jl is a transformation xf that

  • transforms an iterator with xf(itr) (iterator transformation)
  • transforms a reducing step function with xf'(rf) (reducing function transformation)

Common variable names for transducers are xf and xform.

The idea of generalizing the transducer as two kinds of transformation is due to Jan Weidner @jw3126. See the discussion in JuliaFolds/Transducers.jl#67.

Iterator transformation

As of Transducers.jl 0.4.39, the call overload of Transducer is interpreted as an iterator transformation. That is to say, the iterator transformation using Base.Iterators

julia> ixf₁ = itr -> Iterators.filter(isodd, itr);

and the iterator transformation in Transducers.jl

julia> ixf₂ = Filter(isodd);

behaves identically:

julia> collect(ixf₁(1:10)) == collect(ixf₂(1:10))
+true

Filter(isodd)(1:10) is an eduction.

Reducing function transformation

Transducers.jl 0.4.39 also exposes reducing function (RF) transformation with xf'(rf) (adjoint):

julia> rf = Filter(isodd)'(+);  # equivalent to (acc, x) -> isodd(x) ? acc + x : acc;
+
+julia> rf(0, 2)  # `2` filtered out
+0
+
+julia> rf(0, 1)  # `1` not filtered out
+1

Transducer in the narrow sense (Clojure)

The transducer as originally introduced by Rich Hickey is a transformation of reducing step function. Thus, what is referred to as a transducer $\mathrm{xf}$ in Clojure and many other languages is the reducing function transformation xf' in Transducer.jl.

Since a transducer in the narrow sense maps a reducing function to a reducing function, it can be composed with simple function composition $∘$. When a composite transducer $\mathrm{xf} = \mathrm{xf}_1 \circ \mathrm{xf}_2 \circ ... \circ \mathrm{xf}_n$ to a "bottom" reducing function $\mathrm{rf}_0$, it is processed from right to left just like normal functions:

\[\mathrm{rf} = +\mathrm{xf}_1(\mathrm{xf}_2(...(\mathrm{xf}_{n}(\mathrm{rf}_0))))\]

which is equivalent to the following forms in Transducers.jl

rf = xf₁'(xf₂'(...(xfₙ'(rf₀))))
+rf = (xf₁' ∘ xf₂' ∘ ... ∘ xfₙ')(rf₀)
+rf = (xfₙ ∘ ... ∘ xf₂ ∘ xf₁)'(rf₀)
+rf = (xf₁ ⨟ xf₂ ⨟ ... ⨟ xfₙ)(rf₀)

Inner transducer

Given a composition xf₁' ∘ xf₂', transducer xf₂ is said to be the inner transducer of xf₁' ∘ xf₂'. Likewise, xf₂'(rf₀) is an inner reducing function of xf₁'(xf₂'(rf₀)).

Reducible collection

Reducible collection (or just Reducible): Any object that can be passed to foldl and alike is reducible. A reducible collection knows how to apply reducing function to its elements. Iterators are automatically reducible as this is the canonical fallback implementation.

Transducible process

A function that can foldxt reducible collections using transducers is a transducible process. Examples are foldl and foldxt. Find more in Transducible processes.

Executor

An executor such as SequentialEx, ThreadedEx and DistributedEx specifies the execution mechanism of a fold. These executors provide a unified mechanism for choosing underlying execution mechanism for Transducers.jl and its related packages such as Folds.jl and FLoops.jl. Typically, the API functions take an executor as the last optional argument. In addition to the executors provided by Transducers.jl (see Executors section in the manual), additional executors are provided from external packages such as FoldsThreads.jl (various thread-based executors) and FoldsCUDA.jl (a CUDA-based executor).

Transducers.jl's executor is a concept similar to KernelAbstractions.jl' device.

diff --git a/v0.4.83/explanation/internals/index.html b/v0.4.83/explanation/internals/index.html new file mode 100644 index 00000000..f937d61e --- /dev/null +++ b/v0.4.83/explanation/internals/index.html @@ -0,0 +1,190 @@ + +Internals · Transducers.jl

Internals

Transducers.DefaultInitConstant
DefaultInit(op)

DefaultInit is like Init but strictly internal to Transducers.jl. It is used for checking if the bottom reducing function is never called.

source
Transducers.AdHocRFType
AdHocRF(next; oninit, start = identity, complete = identity, combine = next)

Define an ad-hoc reducing function rf.

Note

Use wheninit etc. instead of this constructor.

Arguments

  • next: binary function

Keyword Arguments

  • oninit: nullary function that generates an initial value for next
  • start: unary function that pre-process the initial value for next
  • complete: unary function that post-process the accumulator
  • combine: (approximately) associative binary function for combining multiple results of next (before post-processed by complete).

Examples

julia> using Transducers
+       using Transducers: AdHocRF
+
+julia> rf = AdHocRF(push!, combine = append!);
+
+julia> foldxt(rf, Map(identity), 1:4; basesize = 1, init = OnInit(() -> []))
+4-element Vector{Any}:
+ 1
+ 2
+ 3
+ 4
source
Transducers.AdHocXFType
AdHocXF(f, init, [onlast])

Examples

julia> using Transducers
+
+julia> using Transducers: AdHocXF, @next
+
+julia> using Accessors: @reset
+
+julia> flushlast(rf, result) = rf(@next(rf, result, result.state));
+
+julia> xf = AdHocXF(nothing, flushlast) do rf, result, input
+           m = match(r"^name:(.*)", input)
+           if m === nothing
+               push!(result.state.lines, input)
+               return result
+           else
+               chunk = result.state
+               @reset result.state = (name=strip(m.captures[1]), lines=String[])
+               push!(result.state.lines, input)
+               if chunk === nothing
+                   return result
+               else
+                   return rf(result, chunk)
+               end
+           end
+       end;
+
+julia> collect(xf, split("""
+       name: Map
+       type: onetoone
+       name: Cat
+       type: expansive
+       name: Filter
+       type: contractive
+       name: Cat |> Filter
+       type: chaotic
+       """, "\n"; keepempty=false))
+4-element Vector{@NamedTuple{name::SubString{String}, lines::Vector{String}}}:
+ (name = "Map", lines = ["name: Map", "type: onetoone"])
+ (name = "Cat", lines = ["name: Cat", "type: expansive"])
+ (name = "Filter", lines = ["name: Filter", "type: contractive"])
+ (name = "Cat |> Filter", lines = ["name: Cat |> Filter", "type: chaotic"])
source
Transducers.ReduceSplitByType
Transducers.ReduceSplitBy(f, rf, init)

Split chunks by elements evaluated to true by f and reduce each chunk by reducing function rf.

Note

This is an internal implementation detail of SplitBy for now.

The reducing function rf receives either a Bulk(x) if !f(x) or a End(x) if f(x) returns true. Just just after rf is called with End(x), its accumulator is finalized by complete and then passed to the downstream transducer/reducing function.

Examples

julia> using Transducers
+       using Transducers: ReduceSplitBy, Bulk, End
+
+julia> 1:5 |> ReduceSplitBy(isodd, Map(getindex)'(string), "") |> collect
+3-element Vector{String}:
+ "1"
+ "23"
+ "45"
+
+julia> function just_bulk(x)
+           if x isa Bulk
+               Some(x[])
+           else
+               nothing
+           end
+       end;
+
+julia> 1:5 |> ReduceSplitBy(isodd, KeepSomething(just_bulk)'(string), "") |> collect
+3-element Vector{String}:
+ ""
+ "2"
+ "4"
source
Transducers.UseSIMDType
UseSIMD{ivdep}()

Tell the reducible to run the inner reducing function using @simd. The reducible can support it using @simd_if.

source
Transducers._set_joiner_valueMethod
_set_joiner_value(ps::PrivateState, x) :: PrivateState

Set .state field of the PrivateState of the first "unbalanced" Joiner. A Joiner matched with preceding Splitter would be treated as a regular reducing function node. Thus, private state ps must have one more Joiner than Splitter.

source
Transducers._unzipMethod
_unzip(xs::Tuple)

Examples

julia> _unzip(((1, 2, 3), (4, 5, 6)))
+((1, 4), (2, 5), (3, 6))
source
Transducers.airMethod
air.(broadcasting_expression) :: Broadcasted

Broadcast without materialization.

The idea is taken from @dawbarton's _lazy function: https://discourse.julialang.org/t/19641/20.

source
Transducers.asfoldableMethod

Transducers.asfoldable(x) -> foldable

By default, this function does nothing, but it can be overloaded to convert an input into another type before reducing over it. This allows one to implement a foldable in terms of transducers over an existing type. For instance,

struct VectorOfVectors{T}
+   v::Vector{Vector{T}}
+end
+
+Transducers.asfoldable(vov::VectorOfVectors{T}) = vov.v |> Cat()

Now we can do things like

julia> foldxl(+, VectorOfVectors([[1,2], [3, 4]]))
+10
source
Transducers.combineMethod
Transducers.combine(rf::R_{X}, state_left, state_right)

This is an optional interface for a transducer. If transducer X is stateful (i.e., wrap is used in start), it has to be able to combine the private states to support fold functions that require an associative reducing function such as foldxt. Typical implementation takes the following form:

function combine(rf::R_{X}, a, b)
+    #   ,---- `ua` and `ub` are the private state of the transducer `X`
+    #  /  ,-- `ira` and `irb` are the states of inner reducing functions
+    # /  /
+    ua, ira = unwrap(rf, a)
+    ub, irb = unwrap(rf, b)
+    irc = combine(inner(rf), ira, irb)
+    uc = # somehow combine private states `ua` and `ub`
+    return wrap(rf, uc, irc)
+end

See ScanEmit, etc. for real-world examples.

source
Transducers.completebasecaseMethod
Transducers.completebasecase(rf, state)

Process basecase result state before merged by combine.

For example, on GPU, this function can be used to translate mutable states to immutable values for exchanging them through (un-GC-managed) memory. See whencompletebasecase.

Note

This function is an internal experimental interface for FoldsCUDA.

source
Transducers.extract_transducerMethod
extract_transducer(foldable) -> (xf, foldable′)

"Reverse" of eduction.

Examples

julia> using Transducers
+
+julia> double(x) = 2x;
+
+julia> xs = 1:10;
+
+julia> xf, foldable = Transducers.extract_transducer(Iterators.map(double, xs));
+
+julia> xf == Map(double)
+true
+
+julia> foldable == xs
+true
source
Transducers.initializeMethod
initialize(initializer, op) -> init
+initialize(init, _) -> init

Return an initial value for op. Throw an error if initializer (e.g., Init) creates unknown initial value.

Examples

julia> using Transducers
+       using Transducers: initialize
+
+julia> initialize(Init, +)
+InitialValue(+)
+
+julia> initialize(123, +)
+123
+
+julia> unknown_op(x, y) = x + 2y;
+
+julia> initialize(Init, unknown_op)
+ERROR: IdentityNotDefinedError: `init = Init` is specified but the identity element `InitialValue(op)` is not defined for
+    op = unknown_op
+[...]
source
Transducers.initvalueMethod
initvalue(initializer::AbstractInitializer) -> init
+initvalue(init) -> init

Materialize the initial value if the input is an AbstractInitializer. Return the input as-is if not.

source
Transducers.is_preludeFunction
is_prelude(::T)

Return true if it is better to tail-call when the accumulator or the private state changes its type from T.

source
Transducers.issmallFunction
Transducers.issmall(reducible, basesize) :: Bool

Check if reducible collection is considered small compared to basesize (an integer). Fold functions such as foldxt switches to sequential __foldl__ when issmall returns true.

Default implementation is amount(reducible) <= basesize.

source
Transducers.maybe_usesimdMethod
maybe_usesimd(xform, simd)

Insert UseSIMD to xform if appropriate.

Arguments

  • xform::Transducer
  • simd: false, true, or :ivdep.

Examples

julia> using Transducers
+       using Transducers: maybe_usesimd
+
+julia> maybe_usesimd(reducingfunction(Map(identity), right), false)
+Reduction(
+    Map(identity),
+    BottomRF(
+        Transducers.right))
+
+julia> maybe_usesimd(reducingfunction(Map(identity), right), true)
+Reduction(
+    Transducers.UseSIMD{false}(),
+    Reduction(
+        Map(identity),
+        BottomRF(
+            Transducers.right)))
+
+julia> maybe_usesimd(reducingfunction(Cat(), right), true)
+Reduction(
+    Cat(),
+    Reduction(
+        Transducers.UseSIMD{false}(),
+        BottomRF(
+            Transducers.right)))
+
+julia> maybe_usesimd(opcompose(Map(sin), Cat(), Map(cos))'(right), :ivdep)
+Reduction(
+    Map(sin),
+    Reduction(
+        Cat(),
+        Reduction(
+            Transducers.UseSIMD{true}(),
+            Reduction(
+                Map(cos),
+                BottomRF(
+                    Transducers.right)))))
+
+julia> maybe_usesimd(
+           opcompose(Map(sin), Cat(), Map(cos), Cat(), Map(tan))'(right),
+           true,
+       )
+Reduction(
+    Map(sin),
+    Reduction(
+        Cat(),
+        Reduction(
+            Map(cos),
+            Reduction(
+                Cat(),
+                Reduction(
+                    Transducers.UseSIMD{false}(),
+                    Reduction(
+                        Map(tan),
+                        BottomRF(
+                            Transducers.right)))))))
source
Transducers.retransformMethod
Transducers.retransform(rf, itr) -> rf′, itr′

Extract transformations in rf and itr and use the appropriate adjoint for better performance.

Note that the reducing function extracted from a comprehension such as (f(x) for x ∈ itr) may not be == to f because of the way generator comprehensions work in Julia. Use Iterators.map to specify an exact mapping function.

Examples

julia> using Transducers
+
+julia> double(x) = 2x;
+
+julia> itr0 = 1:10;
+
+julia> itr1 = Iterators.map(double, itr0);
+
+julia> rf, itr2 = Transducers.retransform(+, itr1);
+
+julia> itr2 === itr0
+true
+
+julia> rf == reducingfunction(Map(double), +)
+true
source
Transducers.simple_transduceMethod
simple_transduce(xform, step, init, coll)

Simplified version of transduce. For simple transducers Julia may be able to emit a good code. This function exists only for performance tuning.

source
Transducers.usesimdMethod
usesimd(rf::Reduction, xfsimd::UseSIMD)

Wrap the inner-most loop of reducing function rf with xfsimd. xfsimd is inserted after the inner-most Cat if rf includes Cat.

source
Transducers.whencompletebasecaseFunction
whencompletebasecase(completebasecase, rf) -> rf′
+whencompletebasecase(completebasecase) -> rf -> rf′

Add completebasecase protocol to arbitrary reducing function.

The function completebasecase is used as follows in the basecase implementation of reduce as follows:

init′ = oninit()
+acc = start(init′)
+for x in collection
+    acc += rf(acc, x)
+end
+result = completebasecase(acc)
+return result

The result₁ from basecase 1 and result₂ from basecase 2 are combined using combine protocol:

combine(result₁, result₂)
Note

This function is an internal experimental interface for FoldsCUDA.

source
Transducers.@default_finaltypeMacro
@default_finaltype(xf::Transducer, coll)

Infer the type of the object that would be fed into the second argument input of the bottom reducing function rf(acc, input).

See: Base.@default_eltype

source
Transducers.@simd_ifMacro
@simd_if rf for ... end

Wrap for-loop with @simd if the outer most transducer of the reducing function rf is UseSIMD.

source
diff --git a/v0.4.83/explanation/state_machines/index.html b/v0.4.83/explanation/state_machines/index.html new file mode 100644 index 00000000..d1ad7b1c --- /dev/null +++ b/v0.4.83/explanation/state_machines/index.html @@ -0,0 +1,51 @@ + +State machines · Transducers.jl

Accumulator type transitions as state machines

Some stateful transducers encode the "phase" of reduction as the type of the accumulator (its private state) to achieve efficient composable reductions. This is frequently true especially for parallelizable transducers (i.e., monoid transformations). See the linked docstrings for how each transducer works.

Note

Here, we use the words accumulator and private state interchangeably. However, note that the state shown in the following diagrams only represent a single component in the "composite" accumulator as in acc of __foldl__(rf, acc, xs). For example, for a reducing function

rf = (Consecutive(1, 1) ⨟ ReducePartitionBy(f, rf1))'(rf2)

composed of two transducers and one bottom reducing function rf2, the accumulator acc of it has the type transition that is a composition of Consecutive, ReducePartitionBy, and rf2.

Consecutive(N; step = 1)

Consecutive with step = 1 first accumulate N-1 elements and then start emitting tuples of size N. The private state of the transducer (in each base case) can be illustrated as follows.

For Consecutive(N; step = 1) transducer, the types of the private state are Buffer{0} (initial value), Buffer{1}, Buffer{2}, ..., Buffer{N-2}, and Buffer{N-1}, defined as:

Left{K} = NTuple{K,Any}
+Right{K} = NTuple{K,Any}
+Buffer{K} = Tuple{Left{K}, Right{K}}  # K = 0, 1, ..., N-1

The Right{K} component of Buffer tuple keeps the most recent K elements this transducer received. Once the state reaches to the type Buffer{N-1}, this transducer start emitting an N-tuple for each iteration (as indicated in the edge label NTuple{N,Any}). The loop with the accumulator of type Buffer{N-1} is the major component of the loop (i.e., it is used $O(\mathrm{length(xs)})$ times when reducing an input collection $\mathrm{xs}$). The "main loop" accumulators such as Buffer{N-1} are marked by the double circles. The accumulator types used only for $O(1)$ times are marked by the single circles and called prelude (ref is_prelude). See tail-call "function-barrier" pattern for how this information is used to generate efficient reductions.

The Left{K} component of Buffer tuple keeps the first K elements observed in this base case; this is used only in the parallel reduction, for combining to the base case left to this base case.

The private state of Consecutive with step > 1 additionally contains the counter. It does not contain Left since it cannot be used for parallel reductions.

WordsXF()

Parallel word count tutorial explains how to build a transducer WordsXF that can be used to split words in parallel, in a composable manner. The following diagram shows the transition of its accumulator type. It emits String only after it reaches Vacant, if a word followed by a space is observed (hence Union). See also the definition of extract(::Vacant, ::Vacant) in the tutorial.

ReducePartitionBy(f, rf, [init])

The private state of ReducePartitionBy starts as an Unseen() and then transition to Chunk at the first iteration. It then stays as a Chunk until the result of f(x) for input element x changes for the first time; at this point the state stays as a Vacant that holds the accumulators of rf for the first (left most) chunk and the current chunk. When the value of f(x) is changed for the second time or later, the accumulator of rf is completeed and emitted to the inner reducing function. This is denoted as by the edge label R? in the diagram. The question mark ? is for indicating that the result of type R is not emitted for every iteration; it's only when f(x) is changed.

The Vacant state keeps the first (pre-complete) accumulator of rf so that it can be combineed to the base case left to the current base case.

ReduceSplitBy(f, rf, init)

The private state of ReduceSplitBy starts as a PreChunk and stays as a Chunk until f(x) is true for the input element x. It may jump directly into PreVacant if f(x) is true for the first input element x. From PreVacant, the state is changed to Vacant unless f(x) is true. Each time f(x) is evaluated to true, the accumulator of rf is completeed and its result (of type R) is emitted.

Tail-call "function-barrier" pattern

To improve the type stability of the "main loop" (the transition between the double circles), it is often beneficial to unroll the initial transitions (the single circles). Schematically, we compose code like below:

# Given:
+rf      # reducing function
+acc     # accumulator
+iter    # input collection
+istate  # iterator state
+
+@assert is_prelude(acc)
+T1 = typeof(acc)
+while true
+    y = iterate(iter, istate)
+    y === nothing && return acc
+    (x, istate) = y
+    acc = rf(acc, x)
+    acc isa T1 || break
+end
+
+@assert is_prelude(acc)
+T2 = typeof(acc)
+while true
+    y = iterate(iter, istate)
+    y === nothing && return acc
+    (x, istate) = y
+    acc = rf(acc, x)
+    acc isa T2 || break
+end
+
+# ... and so on ...
+
+@assert is_prelude(acc)
+TN = typeof(acc)
+while true
+    y = iterate(iter, istate)
+    y === nothing && return acc
+    (x, istate) = y
+    acc = rf(acc, x)
+    acc isa TN || break
+end
+
+# Now suppose we are out of the "prelude chain":
+@assert !is_prelude(acc)
+
+# ...then loop like usual:
+while true
+    y = iterate(iter, istate)
+    y === nothing && return acc
+    (x, istate) = y
+    acc = rf(acc, x)
+end

Note that this code snippet is only for explaining the concept. For example, it is not possible to know how many while loops to generate a priori. It also assumes that the transition of the prelude accumulator which is not the case (see, e.g., ReduceSplitBy). Instead, several __foldl__ methods implement this strategy using what we call tail-call function-barrier pattern (ref: an example).

For a previous discussion on this strategy, see also: Tail-call optimization and function-barrier -based accumulation in loops - Internals & Design - JuliaLang.

diff --git a/v0.4.83/howto/empty_result_handling/index.html b/v0.4.83/howto/empty_result_handling/index.html new file mode 100644 index 00000000..d40fa629 --- /dev/null +++ b/v0.4.83/howto/empty_result_handling/index.html @@ -0,0 +1,14 @@ + +Empty result handling · Transducers.jl

Empty result handling

Transducible processes such as foldl try to do the right thing even when init is not given, if the given binary operation step is supported by InitialValues.jl (for example, +, *, &, and | are supported). However, those functions throw an exception if the given collection is empty or filtered out by the transducers:

using Transducers
+
+add1(x) = x + 1
+
+foldl(*, Map(add1), [])
ERROR: EmptyResultError: Reducing function `*` is never called.
+The input collection is empty or the items are all filtered out by some transducer(s). It is recommended to specify `init` to avoid this kind of errors.

To write robust code, it is recommended to use init if there is a reasonable default. However, it may be useful to postpone "materializing" the result. In such case, Init can be used as a placeholder.

result = foldl(*, Map(add1), [], init=Init)

init=Init is a short-hand notation of init=Init(*) (so that * does not have to be repeated):

@assert result === foldl(*, Map(add1), [], init=Init(*))

Note also that transduce can be used for passing init as a positional argument:

@assert result === transduce(Map(add1), Completing(*), Init, [])

Since the input collection [] is empty, result is Init(*) (which is an InitialValues.InitialValue):

using InitialValues: InitialValue
+@assert result::InitialValue === Init(*)

Init(*) is the left identity of *. Multiplying it with any x from right returns x as-is. This property may be useful, e.g., if result is known to be a scalar that is multiplied by a matrix just after the foldl:

result * ones(2, 2)
2×2 Matrix{Float64}:
+ 1.0  1.0
+ 1.0  1.0

The identities Init(*) and Init(+) can be converted to numbers:

convert(Int, Init(*))
1

Init(*) can also be converted to a String:

convert(String, Init(*))
""

This means that no special code is required if the result is going to be stored into, e.g., an Array or a struct:

xs = [true, true]
+xs[1] = Init(+)
+xs
2-element Vector{Bool}:
+ 0
+ 1

They can be converted into numbers also by using Integer:

Integer(Init(+))
0

or float:

float(Init(*))
1.0

This page was generated using Literate.jl.

diff --git a/v0.4.83/howto/reducibles/index.html b/v0.4.83/howto/reducibles/index.html new file mode 100644 index 00000000..b4c2459d --- /dev/null +++ b/v0.4.83/howto/reducibles/index.html @@ -0,0 +1,72 @@ + +Writing reducibles · Transducers.jl

How to make your data type reducible

Let's see how to make a vector-of-vector a reducible collection; i.e., a type that can be fed to foldl.

struct VecOfVec{T}
+    vectors::Vector{Vector{T}}
+end

Method 1: The __foldl__ interface:

We need @next and complete to invoke the reducing function rf.

using Transducers
+using Transducers: @next, complete

Supporting foldl and similar only requires Transducers.__foldl__:

function Transducers.__foldl__(rf, val, vov::VecOfVec)
+    for vector in vov.vectors
+        for x in vector
+            val = @next(rf, val, x)
+        end
+    end
+    return complete(rf, val)
+end

Note that it's often a good idea to implement Base.eltype:

Base.eltype(::VecOfVec{T}) where {T} = T

It can be then used as the input to the transducers:

vov = VecOfVec(collect.([1:n for n in 1:3]))
+collect(Map(identity), vov)
6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3

Macro @next is used instead of function next to avoid the boilerplate for supporting early termination (see the details in in @next documentation). In practice, using @next means that your __foldl__ supports early termination:

vov |> Take(3) |> collect
3-element Vector{Int64}:
+ 1
+ 1
+ 2

More complex example:

vov |> PartitionBy(isequal(1)) |> Zip(Map(copy), Map(sum)) |> collect
4-element Vector{Tuple{Vector{Int64}, Int64}}:
+ ([1, 1], 2)
+ ([2], 2)
+ ([1], 1)
+ ([2, 3], 5)

Method 2: In terms of existing transducers and reducibles with asfoldable

Transducers.jl has a function Transducers.asfoldable which can be overloaded to convert your existing type into a foldable before being fed into __foldl__. This allows us to express a new type in terms of existing structures:

struct VecOfVec2{T}
+    vectors::Vector{T}
+end
+Transducers.asfoldable(vov::VecOfVec2) = vov.vectors |> Cat()

This simply tells Transducers.jl that a VecOfVec2 may be folded over by simply applying the Cat transducer to the .vectors field of the struct. This is enough to reproduce all the examples from the previous section:

vov2 = VecOfVec2(collect.([1:n for n in 1:3]))
+collect(Map(identity), vov2)
6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3
vov2 |> Take(3) |> collect
3-element Vector{Int64}:
+ 1
+ 1
+ 2
vov2 |> PartitionBy(isequal(1)) |> Zip(Map(copy), Map(sum)) |> collect
4-element Vector{Tuple{Vector{Int64}, Int64}}:
+ ([1, 1], 2)
+ ([2], 2)
+ ([1], 1)
+ ([2, 3], 5)

Comparison to defining an Iterator:

Notice that writing Transducers.__foldl__ is very straightforward comparing to how to define an iterator:

function Base.iterate(vov::VecOfVec, state=(1, 1))
+    #Iterator `state` is a tuple of an index `i` to `vov.vectors` and an
+    #index `j` to `vov.vectors[i]`:
+    i, j = state
+    #If `i` is larger than the number of items, we are done:
+    i > length(vov.vectors) && return nothing
+    #If `j` is in bound, we are iterating the same sub-vector:
+    vi = vov.vectors[i]
+    if j <= length(vi)
+        return vi[j], (i, j + 1)
+    end
+    #Otherwise, find the next non-empty sub-vector and start iterating it:
+    for k in i + 1:length(vov.vectors)
+        vk = vov.vectors[k]
+        if !isempty(vk)
+            return vk[1], (k, 2)  # i=k, j=2
+        end
+    end
+    return nothing
+end
+
+Base.length(vov::VecOfVec) = sum(length, vov.vectors)
+
+collect(vov)
6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3

This page was generated using Literate.jl.

diff --git a/v0.4.83/howto/transducers/index.html b/v0.4.83/howto/transducers/index.html new file mode 100644 index 00000000..e465d31c --- /dev/null +++ b/v0.4.83/howto/transducers/index.html @@ -0,0 +1,77 @@ + +Writing transducers · Transducers.jl

How to write transducers

Transducers don't export public interface for implementing transducers (and reducible collections). Let's import some handy ones:

using Transducers
+using Transducers: Transducer, R_, next, inner, xform

Stateless transducer

Let's write manually what opcompose(Filter(x -> x isa Int), Map(x -> x + 1)) would do:

struct AddOneIfInt <: Transducer end
+
+function Transducers.next(rf::R_{AddOneIfInt}, result, input)
+    if input isa Int
+    #Output `input + 1` is passed to the "inner" reducing step:
+        next(inner(rf), result, input + 1)
+    else
+    #Filtering out is done by "doing nothing"; return `result`-so-far
+    #as-is:
+        result
+    end
+end

Ineed, for integer collection, it increments input by one:

collect(AddOneIfInt(), 1:5)
5-element Vector{Int64}:
+ 2
+ 3
+ 4
+ 5
+ 6

Non integer elements are filtered out:

collect(AddOneIfInt(), Any[3, nothing, 2.0, missing, 5])
2-element Vector{Int64}:
+ 4
+ 6

Stateful transducer

AddOneIfInt is a stateless transducer which is very easy to implement. A stateful transducer needs a bit more code.

using Transducers: start, complete, wrap, unwrap, wrapping
+using Random

Let's define a transducer that spits out a random past element from the buffer:

struct RandomRecall <: Transducer
+    history::Int
+    seed::Int
+end
+RandomRecall() = RandomRecall(3, 0)

A stateful transducer needs to implement Transducers.start to "allocate" its private state. Here, the private state is a buffer and a random number generator state rng:

function Transducers.start(rf::R_{RandomRecall}, result)
+    buffer = []
+    rng = MersenneTwister(xform(rf).seed)
+    private_state = (buffer, rng)
+    return wrap(rf, private_state, start(inner(rf), result))
+end

Stateful transducer needs to unwrap its private state inside Transducers.next and then re-wrap it. There is a helper function Transducers.wrapping does that with the do block:

function Transducers.next(rf::R_{RandomRecall}, result, input)
+    wrapping(rf, result) do (buffer, rng), iresult
+    #Pickup a random element to be passed to the inner reducing function.
+    #Replace it with the new incoming one in the buffer:
+        if length(buffer) < xform(rf).history
+            push!(buffer, input)
+            iinput = rand(rng, buffer)
+        else
+            i = rand(rng, 1:length(buffer))
+            iinput = buffer[i]
+            buffer[i] = input
+        end
+        #Call the inner reducing function.  Note that `iresult` unwrapped by
+        iresult = next(inner(rf), iresult, iinput)
+        return (buffer, rng), iresult
+    end
+end

(Transducers.wrapping must be passed to next.)

Any transducer with custom Transducers.start must have a corresponding Transducers.complete. It is responsible for unwrapping the result and call the complete for the inner reducing function.

function Transducers.complete(rf::R_{RandomRecall}, result)
+    _private_state, inner_result = unwrap(rf, result)
+    return complete(inner(rf), inner_result)
+end

Here is how it works:

collect(RandomRecall(), 1:5)
5-element Vector{Int64}:
+ 1
+ 2
+ 2
+ 3
+ 4

Indeed, it picks up some random elements from the past elements. With slightly more complex transducer:

1:100 |> Filter(isodd) |> RandomRecall() |> Filter(x -> x > 10) |> Take(5) |> collect
5-element Vector{Int64}:
+ 11
+ 13
+ 15
+ 19
+ 17

Note that Transducers.complete can do more than unwrap and complete. It is useful for, e.g., flushing the buffer.

function Transducers.complete(rf::R_{RandomRecall}, result)
+    (buffer, _), iresult = unwrap(rf, result)
+    for x in buffer
+    #Note that inner `next` can be called more than one time inside
+    #`next` and `complete`:
+        iresult = next(inner(rf), iresult, x)
+    end
+    #`complete` for inner reducing function must be called exactly once:
+    return complete(inner(rf), iresult)
+end

This then adds 3 (= RandomRecall().history) more elements to the output:

collect(RandomRecall(), 1:5)
8-element Vector{Int64}:
+ 1
+ 2
+ 2
+ 3
+ 4
+ 1
+ 2
+ 5

This page was generated using Literate.jl.

diff --git a/v0.4.83/howto/useful_patterns/index.html b/v0.4.83/howto/useful_patterns/index.html new file mode 100644 index 00000000..4df17d94 --- /dev/null +++ b/v0.4.83/howto/useful_patterns/index.html @@ -0,0 +1,159 @@ + +Useful patterns · Transducers.jl

Useful patterns

This page includes some useful patterns using Transducers.jl.

using Transducers

Flattening nested objects using MapCat

Simple MapCat usage

Consider a vector of "objects" (here just NamedTuples) which in turn contain a vector of objects:

nested_objects = [
+    (a = 1,  b = [(c = 2,  d = 3),  (c = 4,  d = 5)]),
+    (a = 10, b = [(c = 20, d = 30), (c = 40, d = 50)]),
+];

We can flatten this into a table by using Map inside MapCat:

using TypedTables
+astable(xs) = copy(Table, xs)  # using `TypedTables` for a nice display
+
+table1 = nested_objects |> MapCat() do x
+    x.b |> Map() do b  # not `MapCat`
+        (a = x.a, b...)
+    end
+end |> astable
Table with 3 columns and 4 rows:
+     a   c   d
+   ┌───────────
+ 1 │ 1   2   3
+ 2 │ 1   4   5
+ 3 │ 10  20  30
+ 4 │ 10  40  50

(Note that the transducer used inside MapCat is Map, not MapCat)

Nested MapCat

This pattern can handle more nested objects:

more_nested_objects = [
+    (a = 1,  b = [(c = 2,  d = [(e = 3,  f = 4),  (e = 4,  f = 5)]),
+                  (c = 6,  d = [])]),
+    (a = 10, b = [(c = 20, d = [(e = 30, f = 40), (e = 40, f = 50)])]),
+];

By using nested MapCat (except for the "inner most" processing which uses Map since there is nothing to concatenate):

table3 =
+    more_nested_objects |> MapCat() do x
+        x.b |> MapCat() do b
+            b.d |> Map() do d
+                (a = x.a, c = b.c, d...)
+            end
+        end
+    end |> astable
Table with 4 columns and 4 rows:
+     a   c   e   f
+   ┌───────────────
+ 1 │ 1   2   3   4
+ 2 │ 1   2   4   5
+ 3 │ 10  20  30  40
+ 4 │ 10  20  40  50

Comparison with iterator comprehension

As a comparison, here is how to do it with iterator comprehension

rows = (
+    (a = x.a, c = b.c, d...)
+    for x in more_nested_objects
+    for b in x.b
+    for d in b.d
+)
+@assert Table(collect(rows)) == table3

For a simple flattening and mapping, iterator comprehension as above perhaps is the simplest solution.

Note that Transducers.jl works well with iterator comprehensions. Transducers.jl-specific entry points like foldxl converts iterator comprehensions to transducers internally. eduction can be used to explicitly do this conversion:

@assert astable(eduction(rows)) == table3

Complex MapCat example

For more complex processing that requires intermediate variables, the iterator comprehension does not work well. Fortunately, it is easy to use intermediate variables with transducers:

more_nested_objects |>
+MapCat() do x
+    a2 = x.a * 2
+    x.b |> MapCat() do b
+        a2_plus_c = a2 + b.c
+        b.d |> Map() do d
+            c_plus_e = b.c + d.e
+            c_plus_f = b.c + d.f
+            (a2_plus_c = a2_plus_c, c_plus_e = c_plus_e, c_plus_f = c_plus_f)
+        end
+    end
+end |>
+astable
Table with 3 columns and 4 rows:
+     a2_plus_c  c_plus_e  c_plus_f
+   ┌──────────────────────────────
+ 1 │ 4          5         6
+ 2 │ 4          6         7
+ 3 │ 40         50        60
+ 4 │ 40         60        70

MapCat with zip

Note also that MapCat can be combined with arbitrary iterator combinators such as zip

[(a = 1:3, b = 'x':'z'), (a = 1:4, b = 'i':'l')] |>
+MapCat() do x
+    zip(x.a, x.b)
+end |>
+MapSplat((a, b) -> (a = a, b = b)) |>
+astable
Table with 2 columns and 7 rows:
+     a  b
+   ┌─────
+ 1 │ 1  x
+ 2 │ 2  y
+ 3 │ 3  z
+ 4 │ 1  i
+ 5 │ 2  j
+ 6 │ 3  k
+ 7 │ 4  l

MapCat with Iterators.product

... and product

[(a = 1:3, b = 'x':'z'), (a = 1:4, b = 'i':'l')] |>
+MapCat() do x
+    Iterators.product(x.a, x.b)
+end |>
+Enumerate() |>
+Filter(x -> x[1] % 5 == 0) |>  # include only every five item
+MapSplat((n, (a, b)) -> (n = n, a = a, b = b)) |>
+astable
Table with 3 columns and 5 rows:
+     n   a  b
+   ┌─────────
+ 1 │ 5   2  y
+ 2 │ 10  1  i
+ 3 │ 15  2  j
+ 4 │ 20  3  k
+ 5 │ 25  4  l

"Missing value" handling with KeepSomething

Transducers.jl has a generic filtering such as Filter as well as type-based filtering such as NotA and OfType. These transducers can be used to filter out "missing values" represented as missing or nothing.

KeepSomething is a transducer that is useful for working on Union{Nothing,Some{T}}. It filters out nothing and yield itmes after applying something.

[nothing, 1, Some(nothing), 2, 3] |> KeepSomething(identity) |> collect
4-element Vector{Union{Nothing, Int64}}:
+ 1
+  nothing
+ 2
+ 3

Thus, KeepSomething works well with any tools that operate on Union{Nothing,Some{T}}. Here is an example of using it with Maybe.jl. Consider a vector of heterogeneous dictionaries with varying set of keys:

heterogeneous_objects = [
+    Dict(:a => 1, :b => Dict(:c => 2)),
+    Dict(:a => 1),                          # missing key
+    Dict(:a => 1, :b => Dict()),            # missing key
+    Dict(:b => Dict(:c => 2)),              # missing key
+    Dict(:a => 10, :b => Dict(:ccc => 20)), # alternative key name
+];

Using @something and @? macros from Maybe.jl, we can convert this to a regular table quite easily:

using Maybe
+using Maybe: @something
+
+heterogeneous_objects |>
+KeepSomething() do x
+    c = @something {       # (1)
+        @? x[:b][:c];      # (2)
+        @? x[:b][:ccc];    # (3)
+        return;            # (4)
+    }
+    @? (a = x[:a], c = c)  # (5)
+end |>
+astable
Table with 2 columns and 2 rows:
+     a   c
+   ┌───────
+ 1 │ 1   2
+ 2 │ 10  20

In this example, for each dictionary x, the body of the do block works as follows:

  • (1) Try to extract the item c.
    • (2) First, try to get it from x[:b][:c].
    • (3) If x[:b][:c] doesn't exist, try x[:b][:ccc] next.
    • (4) If both x[:b][:c] and x[:b][:ccc] do not exist, return nothing. KeepSomething will filter out this entry.
  • (5) Try to extract the item a from x[:a].
    • If this does not exist, the whole expression wrapped by @? evaluates to nothing. This, in turn, will be filtered out by KeepSomething.
    • If x[:a] exists, @? (a = x[:a], c = c) evaluates to Some((a = value_of_a, c = value_of_c)). The Some wrapper is unwrapped by something called by KeepSomething.

For more information, see the tutorial in Maybe.jl documentation.

Multiple outputs

Usually, reducers like sum and collect have one output. However we can use TeeRF etc. to "fan-out" input items to multiple outputs.

Multiple output vectors

Here is an example of creating two output vectors of integers and symbols in one go:

ints, symbols =
+    [1, :two, missing, 3, 4, :five, 6] |>
+    Filter(!isequal(6)) |>
+    foldxl(TeeRF(
+        OfType(Int)'(push!!),    # push integers to a vector
+        OfType(Symbol)'(push!!), # push symbols to a vector
+    ))
([1, 3, 4], [:two, :five])

Here, we use TeeRF(rf₁, rf₂, ..., rfₙ) to fan-out input items to multiple reducing functions. To compose each reducing function, we use OfType transducer as reducing function transformation xf'(rf).

Handling empty results

Note that fold with push!! throws when the input is empty. To obtain an empty vector when the input is empty or all filtered out, we need to specify init. MicroCollections.jl includes a library of collections useful as init. Here, we can use EmptyVector:

using MicroCollections
+
+ints, strings =
+    [1, :two, missing, 3, 4, :five, 6] |>
+    Filter(!isequal(6)) |>
+    foldxl(TeeRF(
+        OfType(Int)'(push!!),    # push integers to a vector
+        OfType(String)'(push!!), # push strings to a vector (but there is no string)
+    ); init = EmptyVector())
([1, 3, 4], Union{}[])

Composed transducers with TeeRF

Each reducing function passed to TeeRF can use arbitrary complex transducers. Here is an example of filtering-in symbols and then map them to strings:

ints, strings =
+    [1, :two, missing, 3, 4, :five, 6] |>
+    Filter(!isequal(6)) |>
+    foldxl(
+        TeeRF(
+            OfType(Int)'(push!!),
+            opcompose(OfType(Symbol), Map(String))'(push!!),  # filter _then_ map
+        );
+        init = EmptyVector(),
+    )
([1, 3, 4], ["two", "five"])

Nested TeeRF

Each reducing function itself passed to TeeRF can even be composed using TeeRF (or other reducing function combinators; e.g., ProductRF). Here is an example of computing extrema on integers:

(imin, imax), strings =
+    [1, :two, missing, 3, 4, :five, 6] |>
+    Filter(!isequal(6)) |>
+    foldxl(
+        TeeRF(
+            OfType(Int)'(TeeRF(max, min)),  # extrema on integers
+            opcompose(OfType(Symbol), Map(String))'(push!!),  # filter _then_ map
+        );
+        init = ((typemin(Int), typemax(Int)), EmptyVector()),
+    )
((4, 1), ["two", "five"])

When input is a tuple: ProductRF

ProductRF is like TeeRF but it expects that the input is already a tuple:

ints, io =
+    [(1:3, 'x':'z'), nothing, (1:4, 'i':'l')] |>
+    NotA(Nothing) |>
+    foldxl(
+        ProductRF(
+            opcompose(Cat(), Filter(isodd))'(push!!),    # process 1:3 etc.
+            Cat()'((io, char) -> (write(io, char); io)), # process 'x':'z' etc.
+        );
+        init = (EmptyVector(), IOBuffer()),
+    );
String(take!(io))
"xyzijkl"
ints
4-element Vector{Int64}:
+ 1
+ 3
+ 1
+ 3

When input is a row: DataTools.oncol

oncol from DataTools.jl is like ProductRF but acts on NamedTuple (as well as any Accessors.jl-compatible possibly nested objects).

using DataTools
+foldxl(oncol(a = +, b = *), [(a = 1, b = 2), (a = 3, b = 4)])
(a = 4, b = 8)

This page was generated using Literate.jl.

diff --git a/v0.4.83/index.html b/v0.4.83/index.html new file mode 100644 index 00000000..e332f475 --- /dev/null +++ b/v0.4.83/index.html @@ -0,0 +1,30 @@ + +Home · Transducers.jl

Transducers for Julia

Transducers are transformations of "sequence" of input that can be composed very efficiently. The interface used by transducers naturally describes a wide range of processes that is expressible as a succession of steps. Furthermore, transducers can be defined without specifying the details of the input and output (collections, streams, channels, etc.) and therefore achieves a full reusability. Transducers are introduced by Rich Hickey, the creator of the Clojure language. His Strange Loop talk is a great introduction to the idea of transducers.

Transducers.jl is an implementation of the transducers in Julia. Aiming to satisfy high-performance needs of Julia users, Transducers.jl uses a formulation that is pure [pure] and aiding type-stability.

Features

Installation

using Pkg
+Pkg.add("Transducers")

Examples

If you are familiar with iterators (see also Base.Iterators and IterTools.jl) it would look very familiar to you:

julia> using Transducers
+
+julia> 1:3 |> Map(x -> 2x) |> collect  # double each element
+3-element Vector{Int64}:
+ 2
+ 4
+ 6
+
+julia> 1:6 |> Filter(iseven) |> collect  # collect only evens
+3-element Vector{Int64}:
+ 2
+ 4
+ 6
+
+julia> 1:3 |> MapCat(x -> 1:x) |> collect  # concatenate mapped results
+6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3
+

Transducers can be composed:

julia> 1:6 |> Filter(iseven) |> Map(x -> 2x) |> collect
+3-element Vector{Int64}:
+  4
+  8
+ 12

An efficient way to use transducers is combination with foldl. The computation is compiled down to an efficient loop you would write by hand::

julia> foldl(+, 1:6 |> Filter(iseven) |> Map(x -> 2x))
+24

For more detailed discussions on the difference to iterators, see Comparison to iterators.

List of transducers

Here is the list of pre-defined transducers:

TransducerSummary
Broadcasting()Broadcast inner reducing function over elements in the input. Roughly speaking, it transforms the inner reducing function op to op′(a, b) = op.(a, b). However, it has a better memory usage and better initial value handling.
Cat()Concatenate/flatten nested iterators.
Consecutive(size, step = size)Sliding window of width size and interval step. Yield tuples.
Count([start[, step]])Generate a sequence start, start + step, start + step + step, and so on.
Dedupe()De-duplicate consecutive items. Comparison operator which identifies duplicates can be specified by the eq parameter, which defaults to == (equal).
Drop(n)Drop first n items.
DropLast(n)Drop last n items.
DropWhile(pred)Drop items while pred returns true consecutively. It becomes a no-op after pred returns a false.
Enumerate([start[, step]])Transducer variant of Base.enumerate. The start and step arguments are optional and have the same meaning as in Count.
Filter(pred)Skip items for which pred is evaluated to false.
FlagFirst()Output (isfirst, input) where isfirst::Bool is true only for the first iteration and input is the original input.
GroupBy(key, xf::Transducer, [step = right, [init]])Group the input stream by a function key and then fan-out each group of key-value pairs to the eduction xf'(step). This is similar to the groupby relational database operation.
Interpose(sep)Interleave input items with a sep.
Iterated(f, init)Generate a sequence init, f(init), f(f(init)), f(f(f(init))), and so on.
KeepSomething(f = identity)Pass non-nothing output of f to the inner reducing step after possibly unwrapping Some.
Map(f)Apply unary function f to each input and pass the result to the inner reducing step.
MapCat(f)Concatenate output of f which is expected to return an iterable.
MapSplat(f)Like Map(f) but calls f(input...) for each input and then pass the result to the inner reducing step.
NondeterministicThreading(; basesize, ntasks = nthreads())Parallelize inner reducing function using ntasks.
NotA(T)Skip items of type T. Unlike Filter(!ismissing), downstream transducers can have a correct type information for NotA(Missing).
OfType(T)Include only items of type T.
Partition(size, step = size, flush = false)Sliding window of width size and interval step. Yield vectors.
PartitionBy(f)Group input sequence into chunks in which f returns a same value consecutively.
ReduceIf(pred)Stop fold when pred(x) returns true for the output x of the upstream transducer.
ReducePartitionBy(f, rf, [init])Reduce partitions determined by isequal on the output value of f with an associative reducing function rf. Partitions are reduced on-the-fly and no intermediate arrays are allocated.
Replace(assoc)Replace each input with the value in the associative container assoc (e.g., a dictionary, array, string) if it matches with a key/index. Otherwise output the input as-is.
Scan(f, [init = Init])Accumulate input with binary function f and pass the accumulated result so far to the inner reduction step.
ScanEmit(f, init[, onlast])Accumulate input x with a function f with the call signature (u, x) -> (y, u) and pass the result y to the inner reduction step.
TCat(basesize::Integer)Threaded version of Cat (concatenate/flatten).
Take(n)Take n items from the input sequence.
TakeLast(n)Take last n items from the input sequence.
TakeNth(n)Output every n item to the inner reducing step.
TakeWhile(pred)Take items while pred returns true. Abort the reduction when pred returns false for the first time.
Unique(by = identity)Pass only unseen item to the inner reducing step.
Zip(xforms...)Zip outputs of transducers xforms in a tuple and pass it to the inner reduction step.

  • pure...although not pure in the strong sense as Base.@pure.
diff --git a/v0.4.83/interface/index.html b/v0.4.83/interface/index.html new file mode 100644 index 00000000..c4946668 --- /dev/null +++ b/v0.4.83/interface/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/manual/index.html b/v0.4.83/manual/index.html new file mode 100644 index 00000000..c201431d --- /dev/null +++ b/v0.4.83/manual/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v0.4.83/parallelism/index.html b/v0.4.83/parallelism/index.html new file mode 100644 index 00000000..3a68b4ee --- /dev/null +++ b/v0.4.83/parallelism/index.html @@ -0,0 +1,2 @@ + +Parallelism · Transducers.jl

Overview of parallel processing in Transducers.jl

Transducers.jl supports thread-based (foldxt) and process-based (foldxd) parallelisms with the same composable API; i.e. transducers. Having a uniform API to cover different parallelisms as well as sequential processing foldl is useful. Using multiple cores or machines for your computation is as easy as replacing foldl with foldxt or foldxd; you don't need to re-write your transducers or reducing functions.

See also:

Thread-based parallelism

Note

To use multiple threads, the julia process must be started with appropriate environment variable JULIA_NUM_THREADS. See Julia manual for more information about how to enable and verify multi-threading in Julia:

Transducers.jl supports thread-based parallelism for Julia ≥ 1.0. You can use it by replacing foldl with foldxt. With Julia ≥ 1.3, Transducers.jl supports early termination to avoid unnecessary computation while guaranteeing the result to be deterministic; i.e., it does not depend on how computation tasks are scheduled.

Process-based parallelism

Transducers.jl supports process-based parallelism using Distributed.jl. You can use it by replacing foldl with foldxd. It can be used for horizontally scaling the computation. It is also useful for using external libraries that are not "thread-safe."

Note that early termination is not supported in foldxd yet.

diff --git a/v0.4.83/reference/interface/index.html b/v0.4.83/reference/interface/index.html new file mode 100644 index 00000000..bf49aa19 --- /dev/null +++ b/v0.4.83/reference/interface/index.html @@ -0,0 +1,45 @@ + +Interface · Transducers.jl

Transducer interface

Core interface for transducers

Transducers.R_Type
Transducers.R_{X}

When defining a transducer type X, it is often required to dispatch on type rf::R_{X} (Reducing Function) which bundles the current transducer xform(rf)::X and the inner reducing function inner(rf)::R_.

source
Transducers.xformFunction
Transducers.xform(rf::R_{X}) -> xf :: X

Return the transducer xf associated with rf. Returned transducer xf is "atomic"; i.e., it is not a Composition transducer type.

source
Transducers.startFunction
Transducers.start(rf::R_{X}, state)

This is an optional interface for a transducer. Default implementation just calls start of the inner reducing function; i.e.,

start(rf::Reduction, result) = start(inner(rf), result)

If the transducer X is stateful, it can "bundle" its private state with wrap:

start(rf::R_{X}, result) = wrap(rf, PRIVATE_STATE, start(inner(rf), result))

where PRIVATE_STATE is an initial value for the private state that can be used inside next via wrapping.

See Take, PartitionBy, etc. for real-world examples.

Side notes: There is no related API in Clojure's Transducers. Transducers.jl uses it to implement stateful transducers using "pure" functions. The idea is based on a slightly different approach taken in C++ Transducer library atria.

source
Transducers.nextFunction
Transducers.next(rf::R_{X}, state, input)

This is the only required interface. It takes the following form (if start is not defined):

next(rf::R_{X}, result, input) =
+    # code calling next(inner(rf), result, possibly_modified_input)

When calling next, it is almost always a better idea to use the macro form @next. See the details in its documentation.

See Map, Filter, Cat, etc. for real-world examples.

source
Transducers.@nextMacro
@next(rf, state, input)

It is expanded to

result = next(rf, state, input)
+result isa Reduced && return result
+result

This is usually the best way to call next as checking for Reduced is required to support early termination.

See also: next, Reduced, @return_if_reduced.

source
Transducers.completeFunction
Transducers.complete(rf::R_{X}, state)

This is an optional interface for a transducer. If transducer X has some internal state, this is the last chance to "flush" the result.

See PartitionBy, etc. for real-world examples.

If start(rf::R_{X}, state) is defined, complete must unwarp state before returning state to the outer reducing function.

Transducers.jl 0.3

In Transducers.jl 0.2, complete had a fallback implementation to automatically call unwrap when wrap is called in start. Relying on this fallback implementation is now deprecated.

source
Transducers.combineFunction
Transducers.combine(rf::R_{X}, state_left, state_right)

This is an optional interface for a transducer. If transducer X is stateful (i.e., wrap is used in start), it has to be able to combine the private states to support fold functions that require an associative reducing function such as foldxt. Typical implementation takes the following form:

function combine(rf::R_{X}, a, b)
+    #   ,---- `ua` and `ub` are the private state of the transducer `X`
+    #  /  ,-- `ira` and `irb` are the states of inner reducing functions
+    # /  /
+    ua, ira = unwrap(rf, a)
+    ub, irb = unwrap(rf, b)
+    irc = combine(inner(rf), ira, irb)
+    uc = # somehow combine private states `ua` and `ub`
+    return wrap(rf, uc, irc)
+end

See ScanEmit, etc. for real-world examples.

source

Helpers for stateful transducers

Transducers.wrapFunction
wrap(rf::R_{X}, state, iresult)

Pack private state for reducing function rf (or rather the transducer X) with the result iresult returned from the inner reducing function inner(rf). This packed result is typically passed to the outer reducing function.

This is intended to be used only in start. Inside next, use wrapping.

Implementation detail

If iresult is a Reduced, wrap actually unwraps all internal state iresult recursively. However, this is an implementation detail that should not matter when writing transducers.

Consider a reducing step constructed as

rf = opcompose(xf₁, xf₂, xf₃)'(f)

where each xfₙ is a stateful transducer and hence needs a private state stateₙ and this stateₙ is constructed in each start(::R_{typeof(xfₙ)}, result). Then, calling start(rf, result)) is equivalent to

wrap(rf,
+     state₁,                     # private state for xf₁
+     wrap(inner(rf),
+          state₂,                # private state for xf₂
+          wrap(inner(inner(rf)),
+               state₃,           # private state for xf₃
+               result)))

or equivalently

result₃ = result
+result₂ = wrap(inner(inner(rf)), state₃, result₃)
+result₁ = wrap(inner(rf),        state₂, result₂)
+result₀ = wrap(rf,               state₁, result₁)

The inner most step function receives the original result as the first argument while transducible processes such as foldl only sees the outer-most "tree" result₀ during the reduction.

See wrapping, unwrap, and start.

source
Transducers.unwrapFunction
unwrap(rf, result)

Unwrap wraped result to a private state and inner result. Following identity holds:

unwrap(rf, wrap(rf, state, iresult)) == (state, iresult)

This is intended to be used only in complete. Inside next, use wrapping.

source
Transducers.wrappingFunction
wrapping(f, rf, result)

Function f must take two argument state and iresult, and return a tuple (state, iresult). This is intended to be used only in next, possibly with a do block.

next(rf::R_{MyTransducer}, result, input) =
+    wrapping(rf, result) do my_state, iresult
+        # code calling `next(inner(rf), iresult, possibly_modified_input)`
+        return my_state, iresult  # possibly modified
+    end

See wrap, unwrap, and next.

source

Interface for reducibles

Transducers.__foldl__Function
__foldl__(rf, init, reducible::T)

Left fold a reducible with reducing function rf and initial value init. This is primary an API for overloading when the reducible "container" or "context" (e.g., I/O stream) of type T can provide a better reduction mechanism than the default iterator-based one.

For a simple iterable type MyType, a valid implementation is:

function __foldl__(rf, val, itr::MyType)
+    for x in itr
+        val = @next(rf, val, x)
+    end
+    return complete(rf, val)
+end

although in this case default __foldl__ can handle MyType and thus there is no need for defining it. In general, defining __foldl__ is useful only when there is a better way to go over items in reducible than Base.iterate.

See also: @next.

source
Transducers.@return_if_reducedMacro
@return_if_reduced expr

It transforms the given expression to:

val = expr
+val isa Reduced && return val
+val

See also @next.

Transducers.jl 0.3

In v0.2, the calling convention was @return_if_reduced complete(rf, val) and it was transformed to val isa Reduced && return reduced(complete(rf, unreduced(val))). For the rationale behind the change, see this commit message.

Examples

julia> using Transducers: @return_if_reduced
+
+julia> @macroexpand @return_if_reduced f(x)
+quote
+    #158#val = f(x)
+    #= ... =#
+    begin
+        #158#val isa Transducers.Reduced && return #158#val
+        #= ... =#
+        #158#val
+    end
+end
source
diff --git a/v0.4.83/reference/manual/index.html b/v0.4.83/reference/manual/index.html new file mode 100644 index 00000000..c2989fa5 --- /dev/null +++ b/v0.4.83/reference/manual/index.html @@ -0,0 +1,1310 @@ + +Manual · Transducers.jl

Transducers and Transducible processes

Transducible processes

Transducers.foldxlFunction
foldxl(step, xf::Transducer, reducible; init, simd) :: T
+foldxl(step, reducible; init, simd) :: T
+foldl(step, xf::Transducer, reducible; init, simd) :: T
+foldl(step, ed::Eduction; init, simd) :: T
+transduce(xf, step, init, reducible, [executor]; simd) :: Union{T, Reduced{T}}

eXtended left fold. Compose transducer xf with reducing step function step and reduce itr using it.

Note

transduce differs from foldxl as Reduced{T} is returned if the transducer xf or step aborts the reduction and step is not automatically wrapped by Completing.

This API is modeled after transduce in Clojure.

For parallel versions, see foldxt and foldxd.

See also: Empty result handling.

Arguments

  • xf::Transducer: A transducer.
  • step: A callable which accepts 1 and 2 arguments. If it only accepts 2 arguments, wrap it with Completing to "add" 1-argument form (i.e., complete protocol).
  • reducible: A reducible object (array, dictionary, any iterator, etc.).
  • executor: Specify an executor. See SequentialEx.
  • init: An initial value fed to the first argument to reducing step function step. This argument can be omitted for well know binary operations like + or *. Supported binary operations are listed in InitialValues.jl documentation. When Init (not the result of Init, such as Init(*)) is given, it is automatically "instantiated" as Init(step) (where step is appropriately unwrapped if step is a Completing). See Empty result handling in the manual for more information.
  • simd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.

Examples

julia> using Transducers
+
+julia> foldl(Filter(isodd), 1:4, init=0.0) do state, input
+           @show state, input
+           state + input
+       end
+(state, input) = (0.0, 1)
+(state, input) = (1.0, 3)
+4.0
+
+julia> foldxl(+, 1:5 |> Filter(isodd))
+9
+
+julia> 1:5 |> Filter(isodd) |> foldxl(+)
+9

Since TeeRF requires the extended fold protocol, foldl(TeeRF(min, max), [5, 2, 6, 8, 3]) does not work while it works with foldxl:

julia> foldxl(TeeRF(min, max), [5, 2, 6, 8, 3])
+(2, 8)

The unary method of foldlx is useful when combined with |>:

julia> (1:5, 4:-1:1) |> Cat() |> Filter(isodd) |> Enumerate() |> foldxl() do a, b
+           a[2] < b[2] ? b : a
+       end
+(3, 5)
source
Base.foldlFunction
foldl(step, xf::Transducer, reducible; init, simd) :: T
+foldl(step, ed::Eduction; init, simd) :: T

See foldxl.

source
Base.foreachFunction
foreach(eff, xf::Transducer, reducible; simd)
+foreach(eff, ed::Eduction; simd)

Feed the results of xf processing items in reducible into a unary function eff. This is useful when the primary computation at the bottom is the side-effect. It is also equivalent to foreach(eff, eduction(xf, coll)). Note that

foreach(eduction(xf, coll)) do x
+    ...
+end

can be more efficient than

for x in eduction(xf, coll)
+    ...
+end

as the former does not have to translate the transducer protocol to the iterator protocol.

foreach supports all constructs in the native for loop as well as the enhancements [julia_issue_22891] to break with a value (break D(x) below) and append the else clause (E(x) below).

This native for loop

ans = for x in xs
+    A(x)
+    B(x) && break
+    C(x) && break D(x)
+else
+    E(x)
+end

can be written as

ans = foreach(Map(identity), xs) do x
+    A(x)
+    B(x) && return reduced()
+    C(x) && return reduced(D(x))
+    x  # required for passing `x` to `E(x)` below
+end |> ifunreduced() do x
+    E(x)
+end

See: mapfoldl, reduced, ifunreduced.

Transducers.jl 0.3

foreach is changed to return what the do block (eff function) returns as-is in version 0.3. This was required for supporting "for-else" (|> ifunreduced). Previously, it only supported break-with-value and always applied unreduced before it returns.

Examples

julia> using Transducers
+
+julia> foreach(eduction(Filter(isodd), 1:4)) do input
+           @show input
+       end
+input = 1
+input = 3
+3
+
+julia> foreach(Filter(!ismissing), [1, missing, 2, 3]) do input
+           @show input
+           if iseven(input)
+               return reduced()
+           end
+       end
+input = 1
+input = 2
+Reduced(nothing)

It is often useful to append |> unreduced to unwrap Reduced in the final result (note that |> here is the standard function application, not the transducer composition).

julia> foreach(Filter(!ismissing), [1, missing, 2, 3]) do input
+           reduced("got $input")
+       end |> unreduced
+"got 1"

Combination of break-with-value and for-else is useful for triggering action after (e.g.) some kind of membership testing failed:

julia> has2(xs) = foreach(Filter(!ismissing), xs) do input
+           input == 2 && reduced(true)
+       end |> ifunreduced() do input
+           @show input
+           false
+       end;
+
+julia> has2([1, missing, 2, 3])
+true
+
+julia> has2([1, missing])
+input = false
+false

However, note the output input = false in the last example. This is because how && works in Julia

julia> false && "otherwise"
+false

Thus, pure membership testing functions like has2 above can be written in a more concise manner:

julia> simpler_has2(xs) = foreach(Filter(!ismissing), xs) do input
+           input == 2 && reduced(true)
+       end |> unreduced;
+
+julia> simpler_has2([1, missing, 2, 3])
+true
+
+julia> simpler_has2([1, missing])
+false
source
Transducers.foldxtFunction
foldxt(step, xf, reducible; [init, simd, basesize, stoppable, nestlevel]) :: T

eXtended threaded fold (reduce). This is a multi-threaded reduce based on extended fold protocol defined in Transducers.jl.

The "bottom" reduction function step(::T, ::T) :: T must be associative and init must be its identity element.

Transducers composing xf must be stateless (e.g., Map, Filter, Cat, etc.) except for ScanEmit. Note that Scan is not supported (although possible in theory). Early termination requires Julia ≥ 1.3.

Use tcollect or tcopy to collect results into a container.

See also: Parallel processing tutorial, foldxl, foldxd.

Keyword Arguments

  • basesize::Integer = amount(reducible) ÷ nthreads(): A size of chunk in reducible that is processed by each worker. A smaller size may be required when:

    • computation time for processing each item fluctuates a lot
    • computation can be terminated by reduced or transducers using it, such as ReduceIf
  • stoppable::Bool: [This option usually does not have to be set manually.] The threaded fold executed in the "stoppable" mode used for optimizing reduction with reduced has a slight overhead if reduced is not used. This mode can be disabled by passing stoppable = false. It is usually automatically detected and set appropriately. Note that this option is purely for optimization and does not affect the result value.

  • nestlevel::Union{Integer,Val}: Specify how many inner Cat (flatten) transducers to be multi-threaded (using TCat). It must be a positive integer, Val of positive integer, or Val(:inf). Val(:inf) means to use multi-threading for all Cat transducers. Note that Cat transducer should be statically known. That is to say, the fold implementation sees two Cats in ... |> Map(f) |> Cat() |> Cat() but only one Cat in ... |> Map(x -> f(x) |> Cat()) |> Cat() even though they are semantically identical.

  • For other keyword arguments, see foldl.

Transducers.jl 0.4.23

Keyword option stoppable requires at least Transducers.jl 0.4.23.

Examples

julia> using Transducers
+
+julia> foldxt(+, 1:3 |> Map(exp) |> Map(log))
+6.0
+
+julia> using BangBang: append!!
+
+julia> foldxt(append!!, Map(x -> 1:x), 1:2; basesize=1, init=Union{}[])
+3-element Vector{Int64}:
+ 1
+ 1
+ 2
+
+julia> 1:5 |> Filter(isodd) |> foldxt(+)
+9
+
+julia> foldxt(TeeRF(min, max), [5, 2, 6, 8, 3])
+(2, 8)
source
Transducers.foldxdFunction
foldxd(step, xform::Transducer, array; [init, simd, basesize, threads_basesize, pool])

eXtended distributed fold (reduce). This is a distributed reduce based on extended fold protocol defined in Transducers.jl.

Unlike foldxt, early termination by reduced is not supported yet.

Use dcollect or dcopy to collect results into a container.

See also: Parallel processing tutorial, foldxl, foldxt.

Transducers.jl 0.4.3

New in version 0.4.3.

Keyword Arguments

  • pool::AbstractWorkerPool: Passed to Distributed.remotecall.

  • basesize::Integer = amount(array) ÷ nworkers(): A size of chunk in array that is processed by each worker. A smaller size may be required when computation time for processing each item can fluctuate a lot.

  • threads_basesize::Integer = basesize ÷ nthreads(): A size of chunk in array that is processed by each task in each worker process. The default setting assumes that the number of threads used in all workers are the same. For heterogeneous setup where each worker process has different number of threads, it may be required to use smaller threads_basesize and basesize to get a good performance.

  • For other keyword arguments, see foldl.

Examples

julia> using Transducers
+
+julia> foldxd(+, 1:3 |> Map(exp) |> Map(log))
+6.0
+
+julia> 1:5 |> Filter(isodd) |> foldxd(+)
+9
+
+julia> foldxd(TeeRF(min, max), [5, 2, 6, 8, 3])
+(2, 8)
source
Transducers.eductionFunction
eduction(xf::Transducer, coll)
+xf(coll)
+coll |> xf

Create a iterable and reducible object.

This API is modeled after eduction in Clojure.

Note

Even though eduction returns an iterable, it is highly recommended to use the foldl-based method provided by Transducers.jl when the performance is important.

Examples

julia> using Transducers
+
+julia> for x in 1:1000 |> Filter(isodd) |> Take(3)  # slow
+           @show x
+       end
+x = 1
+x = 3
+x = 5
+
+julia> foreach(1:1000 |> Filter(isodd) |> Take(3)) do x  # better
+           @show x
+       end;
+x = 1
+x = 3
+x = 5
source
eduction(iterator::Iterators.Generator)
+eduction(iterator::Iterators.Filter)
+eduction(iterator::Iterators.Flatten)

Convert an iterator to an eduction. The iterators that are typically used in the generator comprehensions are supported.

Transducers.jl 0.3

New in version 0.3.

Examples

julia> using Transducers
+
+julia> iter = (y for x in 1:10 if x % 2 == 0 for y in (x, x + 1));
+
+julia> ed = eduction(iter);
+
+julia> collect(iter) == collect(ed)
+true
source
Base.map!Function
map!(xf::Transducer, dest, src; simd)

Feed src to transducer xf, storing the result in dest. Collections dest and src must have the same shape. Transducer xf may contain filtering transducers. If some entries src are skipped, the corresponding entries in dest will be unchanged. Transducer xf must not contain any expansive transducers such as MapCat.

See also copy!.

Examples

julia> using Transducers
+
+julia> xs = collect(1:5)
+       ys = zero(xs)
+       map!(Filter(isodd), ys, xs)
+5-element Vector{Int64}:
+ 1
+ 0
+ 3
+ 0
+ 5
+
+julia> ans === ys
+true
source
Base.copy!Function
copy!(xf::Transducer, dest, src)

Feed src to transducer xf, storing the result in dest. Collections dest and src may have the same shape. Source src must be iterable. Destination dest must implement empty! and push!.

See also map!.

Examples

julia> using Transducers
+
+julia> copy!(opcompose(PartitionBy(x -> x ÷ 3), Map(sum)), Int[], 1:10)
+4-element Vector{Int64}:
+  3
+ 12
+ 21
+ 19
source
Base.copyFunction
copy(xf::Transducer, T, foldable) :: Union{T, Empty{T}}
+copy(xf::Transducer, foldable::T) :: Union{T, Empty{T}}
+copy([T,] eduction::Eduction) :: Union{T, Empty{T}}

Process foldable with a transducer xf and then create a container of type T filled with the result. Return BangBang.Empty{T} if the transducer does not produce anything. (This is because there is no consistent interface to create an empty container given its type and not all containers support creating an empty container.)

For parallel versions, see tcopy and dcopy.

Transducers.jl 0.4.4

New in version 0.4.4.

Transducers.jl 0.4.8

copy now accepts eductions.

Examples

julia> using Transducers
+       using BangBang: Empty
+
+julia> copy(Map(x -> x => x^2), Dict, 2:2)
+Dict{Int64, Int64} with 1 entry:
+  2 => 4
+
+julia> @assert copy(Filter(_ -> false), Set, 1:1) === Empty(Set)
+
+julia> using TypedTables
+
+julia> @assert copy(Map(x -> (a=x, b=x^2)), Table, 1:1) == Table(a=[1], b=[1])
+
+julia> using StructArrays
+
+julia> @assert copy(Map(x -> (a=x, b=x^2)), StructVector, 1:1) == StructVector(a=[1], b=[1])
+
+julia> using DataFrames
+
+julia> @assert copy(
+           Map(x -> (A = x.a + 1, B = x.b + 1)),
+           DataFrame(a = [1], b = [2]),
+       ) == DataFrame(A = [2], B = [3])
source
Transducers.tcopyFunction
tcopy(xf::Transducer, T, reducible; basesize) :: Union{T, Empty{T}}
+tcopy(xf::Transducer, reducible::T; basesize) :: Union{T, Empty{T}}
+tcopy([T,] itr; basesize) :: Union{T, Empty{T}}

Thread-based parallel version of copy. Keyword arguments are passed to foldxt.

See also: Parallel processing tutorial (especially Example: parallel collect).

Transducers.jl 0.4.5

New in version 0.4.5.

Transducers.jl 0.4.8

tcopy now accepts iterator comprehensions and eductions.

Examples

julia> using Transducers
+
+julia> tcopy(Map(x -> x => x^2), Dict, 2:2)
+Dict{Int64, Int64} with 1 entry:
+  2 => 4
+
+julia> using TypedTables
+
+julia> @assert tcopy(Map(x -> (a=x,)), Table, 1:1) == Table(a=[1])
+
+julia> using StructArrays
+
+julia> @assert tcopy(Map(x -> (a=x,)), StructVector, 1:1) == StructVector(a=[1])

tcopy works with iterator comprehensions and eductions (unlike copy, there is no need for manual conversion with eduction):

julia> table = StructVector(a = [1, 2, 3], b = [5, 6, 7]);
+
+julia> @assert tcopy(
+           (A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a)
+       ) == StructVector(A = [2, 4], B = [4, 6])
+
+julia> @assert tcopy(
+           DataFrame,
+           (A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a)
+       ) == DataFrame(A = [2, 4], B = [4, 6])
+
+julia> @assert table |>
+           Filter(row -> isodd(row.a)) |> Map(row -> (A = row.a + 1, B = row.b - 1)) |>
+           tcopy == StructVector(A = [2, 4], B = [4, 6])

If you have Cat or MapCat at the end of the transducer, consider using foldxt directly:

julia> using Transducers
+       using DataFrames
+
+julia> @assert tcopy(
+           DataFrame,
+           1:2 |> Map(x -> DataFrame(a = [x])) |> MapCat(eachrow);
+           basesize = 1,
+       ) == DataFrame(a = [1, 2])
+
+julia> using BangBang: Empty, append!!
+
+julia> @assert foldxt(
+           append!!,
+           Map(x -> DataFrame(a = [x])),
+           1:2;
+           basesize = 1,
+           # init = Empty(DataFrame),
+       ) == DataFrame(a = [1, 2])

Note that above snippet assumes that it is OK to mutate the dataframe returned by the transducer. Use init = Empty(DataFrame) if this is not the case.

This approach of using foldxt works with other containers; e.g., with TypedTables.Table:

julia> using TypedTables
+
+julia> @assert foldxt(
+           append!!,
+           Map(x -> Table(a = [x])),
+           1:2;
+           basesize = 1,
+           # init = Empty(Table),
+       ) == Table(a = [1, 2])
source
Transducers.dcopyFunction
dcopy(xf::Transducer, T, reducible; [basesize, threads_basesize]) :: Union{T, Empty{T}}
+dcopy(xf::Transducer, reducible::T; [basesize, threads_basesize]) :: Union{T, Empty{T}}
+dcopy([T,] itr; [basesize, threads_basesize]) :: Union{T, Empty{T}}

Distributed.jl-based parallel version of copy. Keyword arguments are passed to foldxd. For examples, see tcopy.

See also: Parallel processing tutorial (especially Example: parallel collect).

Transducers.jl 0.4.5

New in version 0.4.5.

Transducers.jl 0.4.8

dcopy now accepts iterator comprehensions and eductions.

source
Base.append!Function
append!(xf::Transducer, dest, src) -> dest

This API is modeled after into in Clojure.

Warning

The performance of append!(dest, src::Eduction) is poor. Use append!! instead if two-argument form is preferred.

Examples

julia> using Transducers
+
+julia> append!(Drop(2), [-1, -2], 1:5)
+5-element Vector{Int64}:
+ -1
+ -2
+  3
+  4
+  5
source
BangBang.append!!Function
BangBang.append!!(xf::Transducer, dest, src) -> dest′
+BangBang.append!!(dest, src::Eduction) -> dest′

Mutate-or-widen version of append!.

Transducers.jl 0.4.4

New in version 0.4.4.

Transducers.jl 0.4.37

Performance optimization for append!!(dest, src::Eduction) requires version 0.4.37.

Examples

julia> using Transducers, BangBang
+
+julia> append!!(opcompose(Drop(2), Map(x -> x + 0.0)), [-1, -2], 1:5)
+5-element Vector{Float64}:
+ -1.0
+ -2.0
+  3.0
+  4.0
+  5.0
source
Base.collectFunction
collect(xf::Transducer, itr) :: Vector
+collect(ed::Eduction) :: Vector

Process an iterable itr using a transducer xf and collect the result into a Vector.

For parallel versions, see tcollect and dcollect.

Transducers.jl 0.4.8

collect now accepts eductions.

Examples

julia> using Transducers
+
+julia> collect(Interpose(missing), 1:3)
+5-element Vector{Union{Missing, Int64}}:
+ 1
+  missing
+ 2
+  missing
+ 3
source
Transducers.tcollectFunction
tcollect(xf::Transducer, reducible; basesize) :: Union{Vector, Empty{Vector}}
+tcollect(itr; basesize) :: Union{Vector, Empty{Vector}}

Thread-based parallel version of collect. This is just a short-hand notation of tcopy(xf, Vector, reducible). Use tcopy to get a container other than a Vector.

See also: Parallel processing tutorial (especially Example: parallel collect).

Transducers.jl 0.4.5

New in version 0.4.5.

Transducers.jl 0.4.8

tcollect now accepts iterator comprehensions and eductions.

Examples

julia> using Transducers
+
+julia> tcollect(Map(x -> x^2), 1:2)
+2-element Vector{Int64}:
+ 1
+ 4
+
+julia> tcollect(x^2 for x in 1:2)
+2-element Vector{Int64}:
+ 1
+ 4
source
Transducers.dcollectFunction
dcollect(xf::Transducer, reducible; [basesize, threads_basesize]) :: Union{Vector, Empty{Vector}}
+dcollect(itr; [basesize, threads_basesize]) :: Union{Vector, Empty{Vector}}

Distributed.jl-based parallel version of collect. This is just a short-hand notation of dcopy(xf, Vector, reducible). Use dcopy to get a container other than a Vector.

See also: Parallel processing tutorial (especially Example: parallel collect).

Transducers.jl 0.4.5

New in version 0.4.5.

Transducers.jl 0.4.8

dcollect now accepts iterator comprehensions and eductions.

source
Base.ChannelType
Channel(xf::Transducer, itr; kwargs...)
+Channel(ed::Eduction; kwargs...)

Pipe items from an iterable itr processed by the transducer xf through a channel. Channel(xf, itr) and Channel(eduction(xf, itr)) are equivalent. Note that itr itself can be a Channel.

Keyword arguments are passed to Channel(function; kwargs...).

Examples

julia> using Transducers
+
+julia> ch1 = Channel(Filter(isodd), 1:5);
+
+julia> ch2 = Channel(Map(x -> 2x - 1), ch1);
+
+julia> ed = eduction(Map(x -> 1:x), ch2);
+
+julia> ch3 = Channel(Cat(), ed);
+
+julia> foreach(PartitionBy(isequal(1)), ch3) do input
+           @show input
+       end;
+input = [1, 1]
+input = [2, 3, 4, 5]
+input = [1]
+input = [2, 3, 4, 5, 6, 7, 8, 9]
source

Experimental transducible processes

Transducers.channel_unorderedFunction
channel_unordered(xf, input; eltype, size, ntasks, basesize) :: Channel{eltype}
+channel_unordered(itr; eltype, size, ntasks, basesize) :: Channel{eltype}

Provide elements in input processed by a transducer xf through a Channel.

Unary method channel_unordered(itr) produces a Channel that provides elements in the input iterator itr with possibly different order. Iterator comprehensions and eductions can be passed as the input itr.

Use append_unordered! to send outputs to an existing channel.

Transducers.jl 0.4.8

New in version 0.4.8.

Transducers.jl 0.4.9

Unary method channel_unordered(itr) requires Transducers.jl 0.4.9.

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

Keyword Arguments

  • eltype::Type: element type of returned channel
  • size: The size of Channel. A non-negative Int or Inf.
  • ntasks::Int: Number of concurrent tasks. Default to Threads.nthreads().
  • basesize: The "batch size" of the processing; i.e., the number of elements to be processed in a single task. Default to 1.

Examples

julia> using Transducers: Map, channel_unordered
+
+julia> sort!(collect(channel_unordered(Map(x -> x + 1), 1:3)))
+3-element Vector{Any}:
+ 2
+ 3
+ 4
+
+julia> sort!(collect(channel_unordered(x + 1 for x in 1:3 if isodd(x))))
+2-element Vector{Any}:
+ 2
+ 4
source
Transducers.append_unordered!Function
append_unordered!(output, xf, input; ntasks, basesize)
+append_unordered!(output, itr; ntasks, basesize)

Process input elements through a transducer xf and then push! them into output in undefined order.

Binary method append_unordered!(output, itr) is like append!(output, itr) but without order guarantee. Iterator comprehensions and eductions can be passed as the input itr.

output (typically a Channel) must implement thread-safe push!(output, x) method.

See also channel_unordered.

Transducers.jl 0.4.8

New in version 0.4.8.

Transducers.jl 0.4.9

Binary method append_unordered!(output, itr) requires Transducers.jl 0.4.9.

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

Examples

julia> using Transducers: Map, append_unordered!
+
+julia> input = Channel(Map(identity), 1:3);
+
+julia> output = Channel{Int}(0);
+
+julia> task = @async try
+           append_unordered!(output, Map(x -> x + 1), input)
+       finally
+           close(output)
+       end;
+
+julia> sort!(collect(output))
+3-element Vector{Int64}:
+ 2
+ 3
+ 4
+
+julia> input = Channel(Map(identity), 1:3);
+
+julia> output = Channel{Int}(0);
+
+julia> task = @async try
+           append_unordered!(output, (y for x in input if isodd(x) for y in 1:x))
+       finally
+           close(output)
+       end;
+
+julia> sort!(collect(output))
+4-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 3
source

Transducers

Transducers.TransducerType
Transducer

The abstract type for transducers.

A transducer xf can be used as both iterator transformation xf(itr) and reducing function transformation xf'(rf).

See also adjoint for xf'(rf).

Transducers.jl 0.4.39

The call overload xf(rf) requires Transducers.jl 0.4.39 or later.

Note

The call overload xf(rf) requires Julia 1.3 or later. For older Julia versions, use eduction.

Examples

julia> using Transducers
+
+julia> xs = Map(inv)(2:2:4)
+2-element StepRange{Int64, Int64} |>
+    Map(inv)
+
+julia> collect(xs)
+2-element Vector{Float64}:
+ 0.5
+ 0.25
+
+julia> rf = Map(inv)'(+)
+Reduction(
+    Map(inv),
+    BottomRF(
+        +))
+
+julia> rf(1, 4)  # +(1, inv(4))
+1.25
source
CompositionsBase.:⨟Function
g ⨟ f
+opcompose(g, f)

The opposite composition operator defined as

g ⨟ f = f ∘ g
+⨟(f) = f
+⨟(fs...) = ∘(reverse(fs)...)
source
Base.:∘Function
f ⨟ g
+g ∘ f
+opcompose(f, g)
+compose(g, f)

Composition of transducers.

Transducers.jl 0.4.39

Transducers.jl 0.4.39 or later is required for composing transducers with and other operators and functions derived from it.

Transducers written as f |> g |> h in previous versions of Transducers.jl can now be written as f ⨟ g ⨟ h (in Julia 1.5 or later) or opcompose(f, g, h).

Note

"op" in opcompose does not stand for operator; it stands for opposite.

source
Base.adjointFunction
xf'

xf'(rf₁) is a shortcut for calling reducingfunction(xf, rf₁).

More precisely, adjoint xf′ of a transducer xf is a reducing function transform rf₁ -> rf₂. That is to say, xf' a function that maps a reducing function rf₁ to another reducing function rf₂.

Examples

julia> using Transducers
+
+julia> y = Map(inv)'(+)(10, 2)
+10.5
+
+julia> y == +(10, inv(2))
+true
source
Transducers.BroadcastingType
Broadcasting()

Broadcast inner reducing function over elements in the input. Roughly speaking, it transforms the inner reducing function op to op′(a, b) = op.(a, b). However, it has a better memory usage and better initial value handling.

If the input is an array, the array created at the first iteration is reused if it can hold the element types of subsequent iterations. Otherwise, the array type is widen as needed.

If init passed to the fold function is a lazy "initializer" object such as OnInit, it is initialized independently for each item in the first input array. This makes using Broadcasting for (possibly) in-place functions safe.

Transducers.jl 0.4.32

New in version 0.4.32.

Note

Broadcasting transducer is not supported in Julia 1.0.

Examples

julia> using Transducers
+
+julia> foldl(+, Broadcasting(), [[1, 2], [3, 4], 5])
+2-element Vector{Int64}:
+  9
+ 11
+
+julia> foldl(+, Broadcasting(), [(0,), [1], [2.0], [3 + 0im]])
+1-element Vector{ComplexF64}:
+ 6.0 + 0.0im
+
+julia> foldl(
+           *,
+           [[[1], [10, 100]], [[2], [20, 200]], [[3], [30, 300]]] |>
+               Broadcasting() |> Broadcasting(),
+       )
+2-element Vector{Vector{Int64}}:
+ [6]
+ [6000, 6000000]

When processing nested data structure (e.g., array-of-arrays) and mutating accumulator in-place, be careful with sharing the accumulators with each processing of items in the input. For example, this is a bad example:

julia> add!(a, b) = a .+= b;
+
+julia> foldl(add!, Broadcasting(), [[[1], [2, 3]], [[4, 5], 6]];
+             init = Ref([0, 0]))
+2-element Vector{Vector{Int64}}:
+ [13, 15]
+ [13, 15]
+
+julia> ans[1] === ans[2]  # they are the same object
+true

Use OnInit to initialize a new array with each item in the input:

julia> foldl(add!, Broadcasting(), [[[1], [2, 3]], [[4, 5], 6]];
+             init = OnInit(() -> [0, 0]))
+2-element Vector{Vector{Int64}}:
+ [5, 6]
+ [8, 9]
+
+julia> ans == [
+           add!(add!([0, 0], [1]), [4, 5]),
+           add!(add!([0, 0], [2, 3]), 6),
+       ]
+true
source
Transducers.CatType
Cat()

Concatenate/flatten nested iterators.

This API is modeled after cat in Clojure.

Examples

julia> using Transducers
+
+julia> collect(Cat(), [[1, 2], [3], [4, 5]]) == 1:5
+true
source
Transducers.ConsecutiveType
Consecutive(size, step = size)
+Consecutive(size; step = size)

Sliding window of width size and interval step. Yield tuples.

This transducer is like Partition but feeds tuples to the downstream transducers instead of vectors.

If step == 1, this transducer supports parallel reduction for any collections; i.e., Consecutive(size, 1)'(op) is associative if op is associative.

Warning

Currently, in parallel folds, Consecutive(size, 1) cannot be used with reducing functions that can produce a Reduced.

If step > 1, this transducer can, in principle, support parallel reduction if the input collection allows random access (e.g., arrays). However, this feature is not implemented yet.

Examples

julia> using Transducers
+
+julia> 1:8 |> Consecutive(3) |> collect
+2-element Vector{Tuple{Int64, Int64, Int64}}:
+ (1, 2, 3)
+ (4, 5, 6)
+
+julia> 1:8 |> Consecutive(3; step = 1) |> collect
+6-element Vector{Tuple{Int64, Int64, Int64}}:
+ (1, 2, 3)
+ (2, 3, 4)
+ (3, 4, 5)
+ (4, 5, 6)
+ (5, 6, 7)
+ (6, 7, 8)
source
Transducers.CountType
Count([start[, step]])

Generate a sequence start, start + step, start + step + step, and so on.

Note that input is ignored. To use the input in the downstream reduction steps, use Zip.

start defaults to 1 and step defaults to oneunit(start).

See also: Iterators.countfrom. Enumerate

Examples

julia> using Transducers
+
+julia> collect(Zip(Map(identity), Count()), -3:-1)
+3-element Vector{Tuple{Int64, Int64}}:
+ (-3, 1)
+ (-2, 2)
+ (-1, 3)
+
+julia> using Dates
+
+julia> 1:3 |> Zip(Map(identity), Count(Day(1))) |> MapSplat(*) |> collect ==
+       [Day(1), Day(4), Day(9)]
+true
source
Transducers.DedupeType
Dedupe()
+Dedupe(eq)

De-duplicate consecutive items. Comparison operator which identifies duplicates can be specified by the eq parameter, which defaults to == (equal).

This API is modeled after dedupe in Clojure.

Examples

julia> using Transducers
+
+julia> collect(Dedupe(), [1, 1, 2, 1, 3, 3, 2])
+5-element Vector{Int64}:
+ 1
+ 2
+ 1
+ 3
+ 2
source
Transducers.DropType
Drop(n)

Drop first n items.

This API is modeled after drop in Clojure.

Examples

julia> using Transducers
+
+julia> 1:5 |> Drop(3) |> collect
+2-element Vector{Int64}:
+ 4
+ 5
source
Transducers.DropLastType
DropLast(n)

Drop last n items.

This API is modeled after drop-last in Clojure.

Examples

julia> using Transducers
+
+julia> 1:5 |> DropLast(2) |> collect
+3-element Vector{Int64}:
+ 1
+ 2
+ 3
+
+julia> 1:1 |> DropLast(2) |> collect == []
+true
+
+julia> 1:0 |> DropLast(2) |> collect == []
+true
source
Transducers.DropWhileType
DropWhile(pred)

Drop items while pred returns true consecutively. It becomes a no-op after pred returns a false.

This API is modeled after drop-while in Clojure.

Examples

julia> using Transducers
+
+julia> collect(DropWhile(x -> x < 3), [1:5; 1:2])
+5-element Vector{Int64}:
+ 3
+ 4
+ 5
+ 1
+ 2
source
Transducers.EnumerateType
Enumerate([start[, step]])

Transducer variant of Base.enumerate. The start and step arguments are optional and have the same meaning as in Count.

Examples

julia> using Transducers
+
+julia> collect(Enumerate(), ["A", "B", "C"])
+3-element Vector{Tuple{Int64, String}}:
+ (1, "A")
+ (2, "B")
+ (3, "C")
+
+julia> start=2; step=3;
+
+julia> collect(Enumerate(start, step), ["A", "B", "C"])
+3-element Vector{Tuple{Int64, String}}:
+ (2, "A")
+ (5, "B")
+ (8, "C")
+
source
Transducers.FilterType
Filter(pred)

Skip items for which pred is evaluated to false.

This API is modeled after filter in Clojure.

Examples

julia> using Transducers
+
+julia> 1:3 |> Filter(iseven) |> collect
+1-element Vector{Int64}:
+ 2
source
Transducers.FlagFirstType
FlagFirst()

Output (isfirst, input) where isfirst::Bool is true only for the first iteration and input is the original input.

See also: IterTools.flagfirst

Examples

julia> using Transducers
+
+julia> collect(FlagFirst(), 1:3)
+3-element Vector{Tuple{Bool, Int64}}:
+ (1, 1)
+ (0, 2)
+ (0, 3)
source
Transducers.GroupByType
GroupBy(key, xf::Transducer, [step = right, [init]])
+GroupBy(key, rf, [init])

Group the input stream by a function key and then fan-out each group of key-value pairs to the eduction xf'(step). This is similar to the groupby relational database operation.

For example

[1,2,1,2,3] |> GroupBy(string, Map(last)'(+)) |> foldxl(right)

returns a result equivalent to Dict("1"=>2, "2"=>4, "3"=>3) while

[1,2,1,2,3] |> GroupBy(string, Map(last) ⨟ Map(Transducers.SingletonVector), append!!) |> foldxl(right)

returns a result equivalent to Dict("1"=>[1,1], "2"=>[2,2], "3"=>[3,3]).

Alternatively, one can provide a reducing function directly, though this is disfavored since it prevents results from being combined with Transducers.combine and therefore cannot be used with foldxt or foldxd. For example, if GroupBy is used as in:

xs |> Map(upstream) |> GroupBy(key, rf, init) |> Map(downstream)

then the function signatures would be:

upstream(_) :: V
+key(::V) :: K
+rf(::Y, ::Pair{K, V}) ::Y
+downstream(::Dict{K, Y})

That is to say,

  • Ouput of the upstream is fed into the function key that produces the group key (of type K).

  • For each new group key, a new transducible process is started with the initial state init :: Y. Pass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each group.

  • After one "nested" reducing function rf is called, the intermediate result dictionary (of type Dict{K, Y}) accumulating the current and all preceding results is then fed into the downstream.

See also groupreduce in SplitApplyCombine.jl.

Examples

julia> [1,2,3,4] |> GroupBy(iseven, Map(last)'(+)) |> foldxl(right)
+Transducers.GroupByViewDict{Bool,Int64,…}(...):
+  0 => 4
+  1 => 6
julia> using Transducers: SingletonDict;
+
+julia> using BangBang; # for merge!!
+
+julia> x = [(a="A", b=1, c=1), (a="B", b=2, c=2), (a="A", b=3, c=3)];
+
+julia> inner = Map(last) ⨟ Map() do ξ
+           SingletonDict(ξ.b => ξ.c)
+       end;
+
+julia> x |> GroupBy(ξ -> ξ.a, inner, merge!!) |> foldxl(right)
+Transducers.GroupByViewDict{String,Dict{Int64, Int64},…}(...):
+  "B" => Dict(2=>2)
+  "A" => Dict(3=>3, 1=>1)

Note that the reduction stops if one of the group returns a reduced. This can be used, for example, to find if there is a group with a sum grater than 3 and stop the computation as soon as it is find:

julia> result = transduce(
+           GroupBy(
+               string,
+               Map(last) ⨟ Scan(+) ⨟ ReduceIf(x -> x > 3),
+           ),
+           right,
+           nothing,
+           [1, 2, 1, 2, 3],
+       );
+
+julia> result isa Reduced
+true
+
+julia> unreduced(result)
+Transducers.GroupByViewDict{String,Any,…}(...):
+  "1" => 2
+  "2" => 4
source
Transducers.InterposeType
Interpose(sep)

Interleave input items with a sep.

This API is modeled after interpose in Clojure.

Examples

julia> using Transducers
+
+julia> collect(Interpose(missing), 1:3)
+5-element Vector{Union{Missing, Int64}}:
+ 1
+  missing
+ 2
+  missing
+ 3
source
Transducers.IteratedType
Iterated(f, init)

Generate a sequence init, f(init), f(f(init)), f(f(f(init))), and so on.

Note that input is ignored. To use the input in the downstream reduction steps, use Zip.

Pass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.

See also: Scan, ScanEmit.

The idea is taken from IterTools.iterated

Examples

julia> using Transducers
+
+julia> collect(Iterated(x -> 2x, 1), 1:5)
+5-element Vector{Int64}:
+  1
+  2
+  4
+  8
+ 16
+
+julia> collect(Zip(Map(identity), Iterated(x -> 2x, 1)), 1:5)
+5-element Vector{Tuple{Int64, Int64}}:
+ (1, 1)
+ (2, 2)
+ (3, 4)
+ (4, 8)
+ (5, 16)
source
Transducers.KeepSomethingType
KeepSomething(f = identity)

Pass non-nothing output of f to the inner reducing step after possibly unwrapping Some.

This API is modeled after keep in Clojure.

Examples

julia> using Transducers
+
+julia> xf = KeepSomething() do x
+           if x == 0
+               :zero
+           elseif x == 1
+               Some(:one)
+           elseif x == 2
+               Some(nothing)
+           end
+       end;
+
+julia> collect(xf, 0:3)
+3-element Vector{Union{Nothing, Symbol}}:
+ :zero
+ :one
+ nothing

Note that NotA(Nothing) can be used to avoid automatically unwrapping Some:

julia> [Some(1), 2, nothing] |> KeepSomething() |> collect
+2-element Vector{Int64}:
+ 1
+ 2
+
+julia> [Some(1), 2, nothing] |> NotA(Nothing) |> collect
+2-element Vector{Any}:
+  Some(1)
+ 2
source
Transducers.MapType
Map(f)

Apply unary function f to each input and pass the result to the inner reducing step.

This API is modeled after map in Clojure.

Examples

julia> using Transducers
+
+julia> collect(Map(x -> 2x), 1:3)
+3-element Vector{Int64}:
+ 2
+ 4
+ 6
source
Transducers.MapCatType
MapCat(f)

Concatenate output of f which is expected to return an iterable.

This API is modeled after mapcat in Clojure.

Examples

julia> using Transducers
+
+julia> collect(MapCat(x -> 1:x), 1:3)
+6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3
source
Transducers.MapSplatType
MapSplat(f)

Like Map(f) but calls f(input...) for each input and then pass the result to the inner reducing step.

Examples

julia> using Transducers
+
+julia> collect(MapSplat(*), zip(1:3, 10:10:30))
+3-element Vector{Int64}:
+ 10
+ 40
+ 90
source
Transducers.NondeterministicThreadingType
NondeterministicThreading(; basesize, ntasks = nthreads())

Parallelize inner reducing function using ntasks.

Given

#                   ,-- Not parallelized
+#            ______/__
+  foldxl(rf, xs |> xfo |> NondeterministicThreading() |> xfi)
+#        ==                                              ===
+#        Parallelized                                    Parallelized

the inner transducer xfi and the reducing function rf are parallelized but the outer transducer xfo and the iteration over data collection xs are not parallelized.

The scheduling of the tasks (hence the call tree of the inner reducing function) is non-deterministic. It means that the result is deterministic only if the inner reducing function is exactly associative. If the inner reducing function is only approximately associative (e.g., addition of floating point numbers), the result of reduction is likely different for each time.

The outer transducers and iterate are processed sequentially. In particular, the data collection does not have to implement SplittablesBase.halve.

Note

Currently, the default basesize is 1. However, it may be changed in the future (e.g. it may be automatically tuned at run-time).

Note

NondeterministicThreading does not work with Julia < 1.3.

Keyword Arguments

  • basesize::Integer: The number of input elements to be accumulated in a buffer before sent to a task.
  • ntasks::Integer: The number of tasks @spawned. The default value is Threads.nthreads(). A number larger than Threads.nthreads() may be useful if the inner reducing function contains I/O and does not consume too much resource (e.g., memory).

Examples

julia> using Transducers
+
+julia> collect(1:4 |> Filter(isodd))
+2-element Vector{Int64}:
+ 1
+ 3
+
+julia> collect(1:4 |> NondeterministicThreading() |> Filter(isodd))
+2-element Vector{Int64}:
+ 1
+ 3
source
Transducers.NotAType
NotA(T)

Skip items of type T. Unlike Filter(!ismissing), downstream transducers can have a correct type information for NotA(Missing).

See also: OfType

Examples

julia> using Transducers
+
+julia> [1, missing, 2] |> NotA(Missing) |> collect
+2-element Vector{Int64}:
+ 1
+ 2
source
Transducers.OfTypeType
OfType(T)

Include only items of type T.

See also: NotA

Examples

julia> using Transducers
+
+julia> [1, missing, 2] |> OfType(Int) |> collect
+2-element Vector{Int64}:
+ 1
+ 2
source
Transducers.PartitionType
Partition(size, step = size, flush = false)
+Partition(size; step = size, flush = false)

Sliding window of width size and interval step. Yield vectors.

Note: step = size is the default. Hence, the default behavior is non-overlapping windows.

For small size, see Consecutive for a similar transducer that yields tuples instead.

Warning

The vector passed to the inner reducing function is valid only during its immediate reduction step. It must be reduced immediately or copied.

This API is modeled after partition-all in Clojure.

Examples

julia> using Transducers
+
+julia> 1:8 |> Partition(3) |> Map(copy) |> collect
+2-element Vector{Vector{Int64}}:
+ [1, 2, 3]
+ [4, 5, 6]
+
+julia> 1:8 |> Partition(3; flush=true) |> Map(copy) |> collect
+3-element Vector{Vector{Int64}}:
+ [1, 2, 3]
+ [4, 5, 6]
+ [7, 8]
+
+julia> 1:8 |> Partition(3; step=1) |> Map(copy) |> collect
+6-element Vector{Vector{Int64}}:
+ [1, 2, 3]
+ [2, 3, 4]
+ [3, 4, 5]
+ [4, 5, 6]
+ [5, 6, 7]
+ [6, 7, 8]
source
Transducers.PartitionByType
PartitionBy(f)

Group input sequence into chunks in which f returns a same value consecutively.

Warning

The vector passed to the inner reducing function is valid only during its immediate reduction step. It must be reduced immediately or copied.

This API is modeled after partition-by in Clojure.

Examples

julia> using Transducers
+
+julia> 1:9 |> PartitionBy(x -> (x + 1) ÷ 3) |> Map(copy) |> collect
+4-element Vector{UnitRange{Int64}}:
+ 1:1
+ 2:4
+ 5:7
+ 8:9
source
Transducers.ReduceIfType
ReduceIf(pred)

Stop fold when pred(x) returns true for the output x of the upstream transducer.

Examples

julia> using Transducers
+
+julia> foldl(right, ReduceIf(x -> x == 3), 1:10)
+3
source
Transducers.ReducePartitionByType
ReducePartitionBy(f, rf, [init])

Reduce partitions determined by isequal on the output value of f with an associative reducing function rf. Partitions are reduced on-the-fly and no intermediate arrays are allocated.

Examples

Consider the input 1:6 "keyed" by a function x -> x ÷ 3:

julia> map(x -> x ÷ 3, 1:6)
+6-element Vector{Int64}:
+ 0
+ 0
+ 1
+ 1
+ 1
+ 2

i.e., there are three partitions with the key values 0, 1, and 2. We can use ReducePartitionBy to compute, e.g., the length and the sum of each partition by:

julia> using Transducers
+
+julia> 1:6 |> ReducePartitionBy(x -> x ÷ 3, Map(_ -> 1)'(+)) |> collect
+3-element Vector{Int64}:
+ 2
+ 3
+ 1
+
+julia> 1:6 |> ReducePartitionBy(x -> x ÷ 3, +) |> collect
+3-element Vector{Int64}:
+  3
+ 12
+  6
source
Transducers.ReplaceType
Replace(assoc)

Replace each input with the value in the associative container assoc (e.g., a dictionary, array, string) if it matches with a key/index. Otherwise output the input as-is.

This API is modeled after replace in Clojure.

Examples

julia> using Transducers
+
+julia> collect(Replace(Dict('a' => 'A')), "abc")
+3-element Vector{Char}:
+ 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
+ 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+ 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
+
+julia> collect(Replace([:a, :b, :c]), 0:4)
+5-element Vector{Any}:
+ 0
+  :a
+  :b
+  :c
+ 4
+
+julia> collect(Replace("abc"), 0:4)
+5-element Vector{Any}:
+ 0
+  'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
+  'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+  'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
+ 4
source
Transducers.ScanType
Scan(f, [init = Init])

Accumulate input with binary function f and pass the accumulated result so far to the inner reduction step.

The inner reducing step receives the sequence y₁, y₂, y₃, ..., yₙ, ... when the sequence x₁, x₂, x₃, ..., xₙ, ... is fed to Scan(f).

y₁ = f(init, x₁)
+y₂ = f(y₁, x₂)
+y₃ = f(y₂, x₃)
+...
+yₙ = f(yₙ₋₁, xₙ)

This is a generalized version of the prefix sum also known as cumulative sum, inclusive scan, or scan.

Note that the associativity of f is not required when the transducer is used in a process that guarantee an order, such as foldl.

Unless f is a function with known identity element such as +, *, min, max, and append!, the initial state init must be provided.

Pass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.

See also: ScanEmit, Iterated.

Examples

julia> using Transducers
+
+julia> collect(Scan(*), 1:3)
+3-element Vector{Int64}:
+ 1
+ 2
+ 6
+
+julia> 1:3 |> Map(x -> x + im) |> Scan(*) |> collect
+3-element Vector{Complex{Int64}}:
+ 1 + 1im
+ 1 + 3im
+ 0 + 10im
+
+julia> collect(Scan(*, 10), 1:3)
+3-element Vector{Int64}:
+ 10
+ 20
+ 60
source
Transducers.ScanEmitType
ScanEmit(f, init[, onlast])

Accumulate input x with a function f with the call signature (u, x) -> (y, u) and pass the result y to the inner reduction step.

The inner reducing step receives the sequence y₁, y₂, y₃, ..., yₙ, ... computed as follows

u₀ = init
+y₁, u₁ = f(u₀, x₁)
+y₂, u₂ = f(u₁, x₂)
+y₃, u₃ = f(u₂, x₃)
+...
+yₙ, uₙ = f(uₙ₋₁, xₙ)
+...
+yₒₒ = onlast(uₒₒ)

when the sequence x₁, x₂, x₃, ..., xₙ, ... is fed to ScanEmit(f).

Pass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.

See also: Scan, Iterated.

Examples

julia> using Transducers
+
+julia> collect(ScanEmit(tuple, 0), 1:3)
+3-element Vector{Int64}:
+ 0
+ 1
+ 2
source
Transducers.TCatType
TCat(basesize::Integer)

Threaded version of Cat (concatenate/flatten).

To use this transducer, all the downstream (inner) transducers must be stateless (or of type ScanEmit) and the reducing function must be associative. See also: Parallel processing tutorial.

Note that the upstream (outer) transducers need not to be stateless as long as it is called with non-parallel reduction such as foldl and collect.

Examples

julia> using Transducers
+
+julia> 1:3 |> Map(x -> 1:x) |> TCat(1) |> tcollect
+6-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 1
+ 2
+ 3
+
+julia> 1:3 |> Scan(+) |> Map(x -> 1:x) |> TCat(1) |> collect
+10-element Vector{Int64}:
+ 1
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
source
Transducers.TakeType
Take(n)

Take n items from the input sequence.

This API is modeled after take in Clojure.

Examples

julia> using Transducers
+
+julia> 1:10 |> Take(2) |> collect
+2-element Vector{Int64}:
+ 1
+ 2
+
+julia> 1:2 |> Take(5) |> collect
+2-element Vector{Int64}:
+ 1
+ 2

Using a low-level API, it's possible to distinguish if the output is truncated or not:

julia> transduce(Take(3), Completing(push!!), Init, 1:2)
+2-element Vector{Int64}:
+ 1
+ 2
+
+julia> transduce(Take(3), Completing(push!!), Init, 1:4)
+Reduced([1, 2, 3])
+
+julia> transduce(Take(3), Completing(push!!), Init, 1:0)
+InitialValue(push!!)

See also transduce, Reduced and Completing.

source
Transducers.TakeLastType
TakeLast(n)

Take last n items from the input sequence.

Examples

julia> using Transducers
+
+julia> 1:10 |> TakeLast(2) |> collect
+2-element Vector{Int64}:
+  9
+ 10
+
+julia> 1:2 |> TakeLast(5) |> collect
+2-element Vector{Int64}:
+ 1
+ 2
source
Transducers.TakeNthType
TakeNth(n)

Output every n item to the inner reducing step.

This API is modeled after take-nth in Clojure.

Examples

julia> using Transducers
+
+julia> 1:9 |> TakeNth(3) |> collect
+3-element Vector{Int64}:
+ 1
+ 4
+ 7
source
Transducers.TakeWhileType
TakeWhile(pred)

Take items while pred returns true. Abort the reduction when pred returns false for the first time.

This API is modeled after take-while in Clojure.

Examples

julia> using Transducers
+
+julia> [1, 2, 3, 1, 2] |> TakeWhile(x -> x < 3) |> collect
+2-element Vector{Int64}:
+ 1
+ 2
source
Transducers.UniqueType
Unique(by = identity)

Pass only unseen item to the inner reducing step.

The item is distinguished by the output of function by when given.

This API is modeled after distinct in Clojure.

Transducers.jl 0.4.2

New in version 0.4.2.

Examples

julia> using Transducers
+
+julia> [1, 1, 2, -1, 3, 3, 2] |> Unique() |> collect
+4-element Vector{Int64}:
+  1
+  2
+ -1
+  3
+
+julia> [1, 1, 2, -1, 3, 3, 2] |> Unique(x -> x^2) |> collect
+3-element Vector{Int64}:
+ 1
+ 2
+ 3
source
Transducers.ZipMethod
Zip(xforms...)

Zip outputs of transducers xforms in a tuple and pass it to the inner reduction step.

Warning

Head transducers drive tail transducers. Be careful when using it with transducers other than Map, especially the contractive ones like PartitionBy and the expansive ones like MapCat.

Examples

julia> using Transducers
+
+julia> collect(Zip(Map(identity), Map(x -> 10x), Map(x -> 100x)), 1:3)
+3-element Vector{Tuple{Int64, Int64, Int64}}:
+ (1, 10, 100)
+ (2, 20, 200)
+ (3, 30, 300)
source

Experimental transducers

Transducers.ZipSourceType
ZipSource(xform::Transducer)

Branch input into two "flows", inject one into xform and then merge (zip) the output of xform with the original (source) input.

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

To illustrate how it works, consider the following usage

collection |> xf0 |> ZipSource(xf1) |> xf2

where xf0, xf1, and xf2 are some transducers. Schematically, the output yn from xfn flows as follows:

xf0      xf1                       xf2
+---- y0 ------ y1 ---.-- (y0, y1) ----->
+      |              |
+       `-------------'

Examples

julia> using Transducers
+       using Transducers: ZipSource
+
+julia> collect(ZipSource(opcompose(Filter(isodd), Map(x -> x + 1))), 1:5)
+3-element Vector{Tuple{Int64, Int64}}:
+ (1, 2)
+ (3, 4)
+ (5, 6)
source
Transducers.GetIndexType
GetIndex(array)
+GetIndex{inbounds}(array)

Transform an integer input i to array[i].

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

Examples

julia> using Transducers
+       using Transducers: GetIndex
+
+julia> collect(GetIndex('a':'z'), [2, 3, 4])
+3-element Vector{Char}:
+ 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+ 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
+ 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
+
+julia> collect(GetIndex{true}('a':'z'), [2, 3, 4]) # Inbounds
+3-element Vector{Char}:
+ 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+ 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
+ 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
source
Transducers.SetIndexType
SetIndex(array)
+SetIndex{inbounds}(array)

Perform array[i] = v for each input pair (i, v).

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

Examples

julia> using Transducers
+       using Transducers: SetIndex
+
+julia> ys = zeros(3);
+
+julia> foldl(first ∘ tuple, SetIndex(ys), [(1, 11.1), (3, 33.3)], init=nothing)
+
+julia> ys
+3-element Vector{Float64}:
+ 11.1
+  0.0
+ 33.3
source
Transducers.InjectType
Inject(iterator)

Inject the output from iterator to the stream processed by the inner reduction step.

Warning

This API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.

Examples

julia> using Transducers
+       using Transducers: Inject
+
+julia> collect(Inject(Iterators.cycle("hello")), 1:8)
+8-element Vector{Tuple{Int64, Char}}:
+ (1, 'h')
+ (2, 'e')
+ (3, 'l')
+ (4, 'l')
+ (5, 'o')
+ (6, 'h')
+ (7, 'e')
+ (8, 'l')
+
+julia> collect(Inject(Iterators.repeated([1 2])), 1:4)
+4-element Vector{Tuple{Int64, Matrix{Int64}}}:
+ (1, [1 2])
+ (2, [1 2])
+ (3, [1 2])
+ (4, [1 2])
+
+julia> collect(Inject(Iterators.product(1:2, 3:5)), 1:100)
+6-element Vector{Tuple{Int64, Tuple{Int64, Int64}}}:
+ (1, (1, 3))
+ (2, (2, 3))
+ (3, (1, 4))
+ (4, (2, 4))
+ (5, (1, 5))
+ (6, (2, 5))
source

Other reducing function combinators

Transducers.TeeRFType
TeeRF(reducing_functions::Tuple)
+TeeRF(reducing_functions...)

Combine multiple reducing functions into a new reducing function that "multicast" the input to multiple reducing functions.

Roughly speaking, TeeRF(op₁, op₂, ..., opₙ) is equivalent to

((a₁, a₂, ..., aₙ), x) -> (op₁(a₁, x), op₂(a₂, x), ..., opₙ(aₙ, x))

For combine, it behaves like ProductRF.

Transducers.jl 0.4.32

New in version 0.4.32.

Examples

julia> using Transducers
+
+julia> extrema′(xs, xf = Map(identity)) = foldl(TeeRF(min, max), xf, xs);
+
+julia> extrema′([5, 2, 6, 8, 3])
+(2, 8)

Note that the input is considered empty unless all reducing functions call their bottom reducing functions. Specify init to obtain results even when the input collection is empty or all filtered out.

julia> filtering_max = Filter(isodd)'(max);
+
+julia> foldl(TeeRF(min, filtering_max), Map(identity), [5, 2, 6, 8, 3])
+(2, 5)
+
+julia> foldl(TeeRF(min, filtering_max), Map(identity), 2:2:8)
+ERROR: EmptyResultError: ...
+
+julia> foldl(TeeRF(min, filtering_max), Map(identity), 2:2:8; init = Init)
+(2, InitialValue(max))
source
Transducers.ProductRFType
ProductRF(reducing_functions::Tuple)
+ProductRF(reducing_functions...)

Combine N reducing functions into a new reducing function that work on N-tuple. The i-th reducing function receives the i-th element of the input tuple.

Roughly speaking, ProductRF(op₁, op₂, ..., opₙ) is equivalent to

((a₁, a₂, ..., aₙ), (b₁, b₂, ..., bₙ)) -> (op₁(a₁, b₁), op₂(a₂, b₂), ..., opₙ(aₙ, bₙ))
Transducers.jl 0.4.32

New in version 0.4.32.

Examples

Like TeeRF, ProductRF can be used to drive multiple reducing functions. ProductRF is more "low-level" in the sense that TeeRF can be defined in terms of ProductRF (other direction is much harder):

julia> using Transducers
+
+julia> TeeRF′(fs...) = reducingfunction(
+           Map(x -> ntuple(_ -> x, length(fs))),
+           ProductRF(fs...),
+       );
+
+julia> foldl(TeeRF′(min, max), Map(identity), [5, 2, 6, 8, 3])
+(2, 8)

ProductRF may be useful for handling pre-existing stream whose item type is already a tuple:

julia> foldl(ProductRF(&, +), Map(x -> (isodd(x), x)), [5, 2, 6, 8, 3])
+(false, 24)
+
+julia> foldl(TeeRF(reducingfunction(Map(isodd), &), +), Map(identity), [5, 2, 6, 8, 3])
+(false, 24)
source
Transducers.wheninitFunction
wheninit(oninit, rf) -> rf′
+wheninit(oninit) -> rf -> rf′
+whenstart(start, rf) -> rf′
+whenstart(start) -> rf -> rf′
+whencomplete(complete, rf) -> rf′
+whencomplete(complete) -> rf -> rf′
+whencombine(combine, rf) -> rf′
+whencombine(combine) -> rf -> rf′

Add initialization/completion/merging phase to arbitrary reducing function.

The functions passed to those combinators are used as follows in foldl:

init′ = oninit()  # if oninit is given; otherwise standard `init`-preprocessing
+acc = start(init′)
+for x in collection
+    acc += rf(acc, x)
+end
+result = acc
+return complete(result)

In foldxt, a collection is split in multiple parts and then above foldl except for complete is run on them, yielding multiple results which are combined by repeatedly calling combine(result_1, result_2). Note that this allows non-associative function for next while combine must be associative.

See also next, start, complete, and combine.

Arguments

  • rf: reducing function
  • oninit: nullary function that generates an initial value for rf
  • start: unary function that pre-process the initial value for rf
  • complete: unary function that post-process the accumulator
  • combine: (approximately) associative binary function for combining multiple results of rf (before post-processed by complete).

Extended help

Examples

An example for using non-associative reducing function in foldxt:

julia> using Transducers
+
+julia> collector! = push! |> whencombine(append!) |> wheninit(() -> []);
+
+julia> foldxt(collector!, Filter(isodd), 1:5; basesize = 1)
+3-element Vector{Any}:
+ 1
+ 3
+ 5

More "tightly" typed vector can returned by using BangBang.jl interface:

julia> collector!! = push!! |> whencombine(append!!) |> wheninit(Vector{Union{}});
+
+julia> foldxt(collector!!, Filter(isodd), 1:5; basesize = 1)
+3-element Vector{Int64}:
+ 1
+ 3
+ 5

Online averaging algorithm can be implemented, e.g., by:

julia> averaging = function add_average((sum, count), x)
+           (sum + x, count + 1)
+       end |> wheninit() do
+           (Init(+), 0)
+       end |> whencombine() do (sum1, count1), (sum2, count2)
+           (sum1 + sum2), (count1 + count2)
+       end |> whencomplete() do (sum, count)
+           sum / count
+       end;
+
+julia> foldl(averaging, Filter(isodd), 1:5)
+3.0
+
+julia> foldxt(averaging, Filter(isodd), 1:50; basesize = 1)
+25.0

An alternative implementation is to use Map to construct a singleton solution and then merge it into the accumulated solution:

julia> averaging2 = function merge_average((sum1, count1), (sum2, count2))
+           (sum1 + sum2, count1 + count2)
+       end |> whencomplete() do (sum, count)
+           sum / count
+       end |> Map() do x
+           (x, 1)
+       end';  # `'` here is important;
+
+julia> foldl(averaging2, Filter(isodd), 1:5)
+3.0
+
+julia> foldxt(averaging2, Filter(isodd), 1:50; basesize = 1)
+25.0
source

Early termination

Transducers.ReducedType
Reduced

The type signaling transducible processes to abort.

Note

Call reduced function for aborting the transducible process since reduced makes sure x is not doubly wrapped. Reduced is meant to be used as x isa Reduced for checking if the result from transduce is due to early termination.

See reduced, unreduced.

Examples

julia> using Transducers
+
+julia> function step_demo(y, x)
+           if x > 5
+               return reduced(y)
+           else
+               return y + x
+           end
+       end;
+
+julia> result = transduce(Map(identity), Completing(step_demo), 0, 1:10)
+Reduced(15)
+
+julia> result isa Reduced
+true
+
+julia> unreduced(result)
+15
+
+julia> result = transduce(Map(identity), Completing(step_demo), 0, 1:4)
+10
+
+julia> result isa Reduced
+false
+
+julia> unreduced(result)
+10
source
Transducers.reducedFunction
reduced([x = nothing])

Stop transducible process with the final value x (default: nothing). Return x as-is if it already is a reduced value.

See Reduced, unreduced.

This API is modeled after ensure-reduced in Clojure.

Examples

julia> using Transducers
+
+julia> foldl(Enumerate(), "abcdef"; init=0) do y, (i, x)
+           if x == 'd'
+               return reduced(y)
+           end
+           return y + i
+       end
+6
+
+julia> foreach(Enumerate(), "abc") do (i, x)
+           println(i, ' ', x)
+           if x == 'b'
+               return reduced()
+           end
+       end;
+1 a
+2 b
source
Transducers.ifunreducedFunction
ifunreduced(f, [x])

Equivalent to unreduced(x) if x is a Reduced; otherwise run f(x). Return a curried version if x is not provided.

See: foreach.

Examples

julia> using Transducers
+
+julia> 1 |> ifunreduced() do x
+           println("called with x = ", x)
+       end
+called with x = 1
+
+julia> reduced(1) |> ifunreduced() do x
+           println("called with x = ", x)
+       end
+1

Notice that nothing is printed in the last example.

Implementation

ifunreduced(f) = x -> ifunreduced(f, x)
+ifunreduced(f, x::Reduced) = unreduced(x)
+ifunreduced(f, x) = f(x)
source

Executors

Transducers.SequentialExType
SequentialEx(; simd)

Sequential fold executor. It can be passed to APIs from packages such as Folds.jl and FLoops.jl to run the algorithm sequentially.

See also: foldxl, ThreadedEx and DistributedEx.

Keyword Arguments

  • simd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.

Examples

julia> using Folds
+
+julia> Folds.sum(1:3, SequentialEx())
+6
source
Transducers.ThreadedExType
ThreadedEx(; basesize, stoppable, nestlevel, simd)

Multi-threaded fold executor. This is the default [1] parallel executor used by Folds.jl and FLoops.jl.

See also: foldxt, SequentialEx and DistributedEx.

Keyword Arguments

  • basesize::Integer = amount(reducible) ÷ nthreads(): A size of chunk in reducible that is processed by each worker. A smaller size may be required when:

    • computation time for processing each item fluctuates a lot
    • computation can be terminated by reduced or transducers using it, such as ReduceIf
  • stoppable::Bool: [This option usually does not have to be set manually.] The threaded fold executed in the "stoppable" mode used for optimizing reduction with reduced has a slight overhead if reduced is not used. This mode can be disabled by passing stoppable = false. It is usually automatically detected and set appropriately. Note that this option is purely for optimization and does not affect the result value.

  • nestlevel::Union{Integer,Val}: Specify how many inner Cat (flatten) transducers to be multi-threaded (using TCat). It must be a positive integer, Val of positive integer, or Val(:inf). Val(:inf) means to use multi-threading for all Cat transducers. Note that Cat transducer should be statically known. That is to say, the fold implementation sees two Cats in ... |> Map(f) |> Cat() |> Cat() but only one Cat in ... |> Map(x -> f(x) |> Cat()) |> Cat() even though they are semantically identical.

  • simd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.

Examples

julia> using Folds
+
+julia> Folds.sum(1:3, ThreadedEx(basesize = 1))
+6
source
Transducers.DistributedExType
DistributedEx(; pool, basesize, threads_basesize, simd)

Distributed fold executor. It can be passed to APIs from packages such as Folds.jl and FLoops.jl to run the algorithm sequentially.

See also: foldxd, SequentialEx and ThreadedEx.

Keyword Arguments

  • pool::AbstractWorkerPool: Passed to Distributed.remotecall.

  • basesize::Integer = amount(array) ÷ nworkers(): A size of chunk in array that is processed by each worker. A smaller size may be required when computation time for processing each item can fluctuate a lot.

  • threads_basesize::Integer = basesize ÷ nthreads(): A size of chunk in array that is processed by each task in each worker process. The default setting assumes that the number of threads used in all workers are the same. For heterogeneous setup where each worker process has different number of threads, it may be required to use smaller threads_basesize and basesize to get a good performance.

  • simd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.

Examples

julia> using Folds
+
+julia> Folds.sum(1:3, DistributedEx())
+6
source
Transducers.PreferParallelType
PreferParallel(; simd, basesize)

A "placeholder" executor that indicates preference to parallel execution.

This lets the input data collection decide preferred execution strategy (e.g., CUDAEx for CuArray when FoldsCUDA.jl is available), assuming that the reducing function is associative. The default executor is ThreadedEx. As an optional feature, some input data collections support (e.g., AbstractChannel) automatically demoting the execution strategy to SequentialEx. An error is thrown if the automatic detection fails,

source

Miscellaneous

Transducers.SplitByType
SplitBy(f; [keepend = false,] [keepempty = false,])

Split input collection into chunks delimited by the elements on which f returns true. This can be used to implement parallel and lazy versions of functions like eachline and split.

If keepend is true (or Val(true)), include the "delimiter"/end element at the end of each chunk. If keepempty is true (or Val(true)), include empty chunks. When keepend is true, the value of keepempty is irrelevant since the chunks cannot be empty (i.e., it at least contains the end).

The input collection (xs in SplitBy(...)(xs)) has to support eachindex and view or SubString.

Extended Help

Examples

For demonstration, consider the following input stream and SplitBy(iszero; ...) used with the following options:

input     keepend=false       keepend=false        keepend=true
+          keepempty=false     keepempty=true
+
+1           `.                  `.                  `.
+2            | y1                | y1                | y1
+3           ,'                  ,'                   |
+0                                                   ,'
+1           `.                  `.                  `.
+2            | y2                | y2                | y2
+3            |                   |                   |
+4           ,'                  ,'                   |
+0                               __ y3               ,'
+0                                                    ] y3
+1           `.                  `.                  `.
+2            | y3                | y4                | y4

In the above diagram, yi (i = 1, 2, 3, 4) are the output of SplitBy. This can be checked in the REPL easily as follows. (Note: we are using Map(collect) for cleaner printing; it's not required unless the arrays is mutated in the downstream.)

julia> using Transducers
+
+julia> xs = [1, 2, 3, 0, 1, 2, 3, 4, 0, 0, 1, 2];  # input
+
+julia> xs |> SplitBy(iszero) |> Map(collect) |> collect
+3-element Vector{Vector{Int64}}:
+ [1, 2, 3]
+ [1, 2, 3, 4]
+ [1, 2]
+
+julia> xs |> SplitBy(iszero; keepempty = true) |> Map(collect) |> collect
+4-element Vector{Vector{Int64}}:
+ [1, 2, 3]
+ [1, 2, 3, 4]
+ []
+ [1, 2]
+
+julia> xs |> SplitBy(iszero; keepend = true) |> Map(collect) |> collect
+4-element Vector{Vector{Int64}}:
+ [1, 2, 3, 0]
+ [1, 2, 3, 4, 0]
+ [0]
+ [1, 2]
source
Transducers.TransducerMethod
Transducer(iterator::Iterators.Generator)
+Transducer(iterator::Iterators.Filter)
+Transducer(iterator::Iterators.Flatten)

Extract "processing" part of an iterator as a Transducer. The "data source" iterator (i.e., xs in (f(x) for x in xs)) is ignored and nothing must be used as a place holder (i.e., (f(x) for x in nothing)).

See also eduction.

Transducers.jl 0.3

New in version 0.3.

Examples

julia> using Transducers
+
+julia> xf1 = Transducer(2x for x in nothing if x % 2 == 0);
+
+julia> xf2 = opcompose(Filter(x -> x % 2 == 0), Map(x -> 2x));  # equivalent
+
+julia> xs = 1:10
+       collect(xf1, xs) == collect(xf2, xs)
+true
source
Transducers.reducingfunctionFunction
reducingfunction(xf, step; simd)
+xf'(step; simd)

Apply transducer xf to the reducing function step to create a new reducing function.

Transducers.jl 0.3

New in version 0.3.

Warning

Be careful using reducingfunction with stateful transducers like Scan with mutable init (e.g., Scan(push!, [])). See more in Examples below.

Arguments

  • xf::Transducer: A transducer.
  • step: A callable which accepts 1 and 2 arguments. If it only accepts 2 arguments, wrap it with Completing to "add" 1-argument form (i.e., complete protocol).

Keyword Arguments

Examples

julia> using Transducers
+
+julia> rf = reducingfunction(Map(x -> x + 1), *);
+
+julia> rf(10, 2) === 10 * (2 + 1)
+true

Warning: Be careful when using reducingfunction with stateful transducers

Stateful Transducers themselves in Transducers.jl are not inherently broken with reducingfunction. However, it can produce incorrect results when combined with mutable states:

julia> scan_state = [];
+
+julia> rf_bad = opcompose(Scan(push!, scan_state), Cat())'(string);
+
+julia> transduce(rf_bad, "", 1:3)
+"112123"

The first run works. However, observe that the vector scan_state is not empty anymore:

julia> scan_state
+3-element Vector{Any}:
+ 1
+ 2
+ 3

Thus, the second run produces an incorrect result:

julia> transduce(rf_bad, "", 1:3)
+"123112312123123"

One way to solve this issue is to use CopyInit or OnInit.

julia> scan_state = CopyInit([])
+CopyInit(Any[])
+
+julia> rf_good = opcompose(Scan(push!, scan_state), Cat())'(string);
+
+julia> transduce(rf_good, "", 1:3)
+"112123"
+
+julia> scan_state
+CopyInit(Any[])
+
+julia> transduce(rf_good, "", 1:3)
+"112123"
source
Transducers.InitConstant
Init
+Init(op) :: InitialValues.InitialValue

The canonical initializer; i.e., a singleton placeholder usable for init argument of foldl for binary functions with known initial values.

When init = Init is passed to foldl etc., Init(op) is called for the bottom reducing function op during the start phase. Init(op) returns InitialValue(op) which acts as the canonical initial value of op.

Examples

julia> using Transducers
+
+julia> foldl(+, 1:3 |> Filter(isodd); init = Init)
+4
+
+julia> foldl(+, 2:2:4 |> Filter(isodd); init = Init)
+InitialValue(+)

Extended help

Note that op passed to foldl etc. must be known to InitialValues.jl:

julia> unknown_op(a, b) = a + b;
+
+julia> foldl(unknown_op, 2:2:4 |> Filter(isodd); init = Init)
+ERROR: IdentityNotDefinedError: `init = Init` is specified but the identity element `InitialValue(op)` is not defined for
+    op = unknown_op
+[...]

InitialValues.asmonoid can be used to wrap a binary function to add ("adjoin") the identity value to its domain:

julia> using InitialValues: asmonoid
+
+julia> foldl(asmonoid(unknown_op), 2:2:4 |> Filter(isodd); init = Init)
+InitialValue(::InitialValues.AdjoinIdentity{typeof(unknown_op)})

When start(rf, Init) is called with a composite reducing function rf, Init(rf₀) is called for the bottom reducing function rf₀ of rf:

julia> rf = Take(3)'(+);  # `+` is the bottom reducing function;
+
+julia> acc = Transducers.start(rf, Init);
+
+julia> Transducers.unwrap(rf, acc)
+(3, InitialValue(+))
source
Transducers.OnInitType
OnInit(f)

Call a callable f to create an initial value.

See also CopyInit.

OnInit or CopyInit must be used whenever using in-place reduction with foldxt etc.

Examples

julia> using Transducers
+
+julia> xf1 = Scan(push!, [])
+Scan(push!, Any[])
+
+julia> foldl(right, xf1, 1:3)
+3-element Vector{Any}:
+ 1
+ 2
+ 3
+
+julia> xf1
+Scan(push!, Any[1, 2, 3])

Notice that the array is stored in xf1 and mutated in-place. As a result, second run of foldl contains the results from the first run:

julia> foldl(right, xf1, 10:11)
+5-element Vector{Any}:
+  1
+  2
+  3
+ 10
+ 11

This may not be desired. To avoid this behavior, create an OnInit object which takes a factory function to create a new initial value.

julia> xf2 = Scan(push!, OnInit(() -> []))
+Scan(push!, OnInit(##9#10()))
+
+julia> foldl(right, xf2, 1:3)
+3-element Vector{Any}:
+ 1
+ 2
+ 3
+
+julia> foldl(right, xf2, [10.0, 11.0])
+2-element Vector{Any}:
+ 10.0
+ 11.0

Keyword argument init for transducible processes also accept an OnInit:

julia> foldl(push!, Map(identity), "abc"; init=OnInit(() -> []))
+3-element Vector{Any}:
+ 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
+ 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+ 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

To create a copy of a mutable object, CopyInit is easier to use.

However, more powerful and generic pattern is to use push!! from BangBang.jl and initialize init with Union{}[] so that it automatically finds the minimal element type.

julia> using BangBang
+
+julia> foldl(push!!, Map(identity), "abc"; init=Union{}[])
+3-element Vector{Char}:
+ 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
+ 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
+ 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
source
Transducers.CopyInitType
CopyInit(value)

This is equivalent to OnInit(() -> deepcopy(value)).

Transducers.jl 0.3

New in version 0.3.

Examples

julia> using Transducers
+
+julia> init = CopyInit([]);
+
+julia> foldl(push!, Map(identity), 1:3; init=init)
+3-element Vector{Any}:
+ 1
+ 2
+ 3
+
+julia> foldl(push!, Map(identity), 1:3; init=init)  # `init` can be reused
+3-element Vector{Any}:
+ 1
+ 2
+ 3
source
Transducers.rightFunction
right([l, ]r) -> r

It is simply defined as

right(l, r) = r
+right(r) = r

This function is meant to be used as step argument for foldl etc. for extracting the last output of the transducers.

Transducers.jl 0.3

Initial value must be manually specified. In 0.2, it was automatically set to nothing.

Examples

julia> using Transducers
+
+julia> foldl(right, Take(5), 1:10)
+5
+
+julia> foldl(right, Drop(5), 1:3; init=0)  # using `init` as the default value
+0
source
Transducers.setinputFunction
setinput(ed::Eduction, coll)

Set input collection of eduction ed to coll.

Transducers.jl 0.3

Previously, setinput combined with eduction was a recommended way to use transducers in a type stable manner. As of v0.3, all the foldl-like functions and eduction are type stable for many cases. This workaround is no more necessary.

Examples

julia> using Transducers
+
+julia> ed = eduction(Map(x -> 2x), Float64[]);
+
+julia> xs = ones(2, 3);
+
+julia> foldl(+, setinput(ed, xs))
+12.0
source
Transducers.AdHocFoldableType
AdHocFoldable(foldl, [collection = nothing])

Provide a different way to fold collection without creating a wrapper type.

Arguments

  • foldl::Function: a function that implements __foldl__.
  • collection: a collection passed to the last argument of foldl.

Examples

julia> using Transducers
+       using Transducers: @next, complete
+       using ArgCheck
+
+julia> function uppertriangle(A::AbstractMatrix)
+           @argcheck !Base.has_offset_axes(A)
+           return AdHocFoldable(A) do rf, acc, A
+               for j in 1:size(A, 2), i in 1:min(j, size(A, 1))
+                   acc = @next(rf, acc, @inbounds A[i, j])
+               end
+               return complete(rf, acc)
+           end
+       end;
+
+julia> A = reshape(1:6, (3, 2))
+3×2 reshape(::UnitRange{Int64}, 3, 2) with eltype Int64:
+ 1  4
+ 2  5
+ 3  6
+
+julia> collect(Map(identity), uppertriangle(A))
+3-element Vector{Int64}:
+ 1
+ 4
+ 5
+
+julia> function circularwindows(xs::AbstractVector, h::Integer)
+           @argcheck !Base.has_offset_axes(xs)
+           @argcheck h >= 0
+           @argcheck 2 * h + 1 <= length(xs)
+           return AdHocFoldable(xs) do rf, acc, xs
+               buffer = similar(xs, 2 * h + 1)
+               @inbounds for i in 1:h
+                   buffer[1:h - i + 1] .= @view xs[end - h + i:end]
+                   buffer[h - i + 2:end] .= @view xs[1:h + i]
+                   acc = @next(rf, acc, buffer)
+               end
+               for i in h + 1:length(xs) - h
+                   acc = @next(rf, acc, @inbounds @view xs[i - h:i + h])
+               end
+               @inbounds for i in 1:h
+                   buffer[1:end - i] .= @view xs[end - 2 * h + i:end]
+                   buffer[end - i + 1:end] .= @view xs[1:i]
+                   acc = @next(rf, acc, buffer)
+               end
+               return complete(rf, acc)
+           end
+       end;
+
+julia> collect(Map(collect), circularwindows(1:9, 2))
+9-element Vector{Vector{Int64}}:
+ [8, 9, 1, 2, 3]
+ [9, 1, 2, 3, 4]
+ [1, 2, 3, 4, 5]
+ [2, 3, 4, 5, 6]
+ [3, 4, 5, 6, 7]
+ [4, 5, 6, 7, 8]
+ [5, 6, 7, 8, 9]
+ [6, 7, 8, 9, 1]
+ [7, 8, 9, 1, 2]
+
+julia> expressions(str::AbstractString; kwargs...) =
+           AdHocFoldable(str) do rf, val, str
+               pos = 1
+               while true
+                   expr, pos = Meta.parse(str, pos;
+                                          raise = false,
+                                          depwarn = false,
+                                          kwargs...)
+                   expr === nothing && break
+                   val = @next(rf, val, expr)
+               end
+               return complete(rf, val)
+           end;
+
+julia> collect(Map(identity), expressions("""
+       x = 1
+       y = 2
+       """))
+2-element Vector{Expr}:
+ :(x = 1)
+ :(y = 2)
+
+julia> counting = AdHocFoldable() do rf, acc, _
+           i = 0
+           while true
+               i += 1
+               acc = @next(rf, acc, i)
+           end
+       end;
+
+julia> foreach(counting) do i
+           @show i;
+           i == 3 && return reduced()
+       end;
+i = 1
+i = 2
+i = 3
source
Transducers.withprogressFunction
withprogress(foldable) -> foldable′

Wrap a foldable so that progress is shown in logging-based progress meter (e.g., Juno) during foldl, foldxt, foldxd, etc.

For parallel reduction such as foldxt and foldxd, reasonably small basesize and threads_basesize (for foldxd) must be used to ensure that progress information is updated frequently. However, it may slow down the computation if basesize is too small.

Keyword Arguments

  • interval::Real: Minimum interval (in seconds) for how often progress is logged.

Examples

julia> using Transducers
+
+julia> xf = Map() do x
+           sleep(0.01)
+           x
+       end;
+
+julia> foldl(+, xf, withprogress(1:100; interval=1e-3))  # see progress meter
+5050

In foldl and foldxt, withprogress can be nested. This is not supported in foldxd.

julia> xf = opcompose(
+           MapCat() do x
+               withprogress(1:x; interval=1e-3)  # nested progress
+           end,
+           Map() do x
+               sleep(0.5)
+               x
+           end,
+       );
+
+julia> foldxt(+, xf, withprogress(1:10; interval=1e-3); basesize=1)
+220
source
Base.mapfoldlFunction
mapfoldl(xf::Transducer, step, reducible; init, simd)
Warning

mapfoldl(::Transducer, rf, itr) is deprecated. Use foldl(rf, ::Transducer, itr) if you do not need to call single-argument rf on complete. Use foldl(whencomplete(rf, rf), ::Transducer, itr) to call the single-argument method of rf on complete.

Like foldl but step is not automatically wrapped by Completing.

Examples

julia> using Transducers
+
+julia> function step_demo(state, input)
+           @show state, input
+           state + input
+       end;
+
+julia> function step_demo(state)
+           println("Finishing with state = ", state)
+           state
+       end;
+
+julia> mapfoldl(Filter(isodd), step_demo, 1:4, init=0.0)
+(state, input) = (0.0, 1)
+(state, input) = (1.0, 3)
+Finishing with state = 4.0
+4.0
source
Base.mapreduceFunction
mapreduce(xf, step, reducible; init, simd)
Warning

mapreduce(::Transducer, rf, itr) is deprecated. Use foldxt(rf, ::Transducer, itr) if you do not need to call single-argument rf on complete. Use foldxt(whencomplete(rf, rf), ::Transducer, itr) to call the single-argument method of rf on complete.

Like foldxt but step is not automatically wrapped by Completing.

source
diff --git a/v0.4.83/search_index.js b/v0.4.83/search_index.js new file mode 100644 index 00000000..4aa529d0 --- /dev/null +++ b/v0.4.83/search_index.js @@ -0,0 +1,3 @@ +var documenterSearchIndex = {"docs": +[{"location":"explanation/glossary/#Glossary","page":"Glossary","title":"Glossary","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"foldl(step, xf, input, init=...)\n# | | | |\n# | | | `-- reducible\n# | | |\n# | | `-- transducer\n# | |\n# | `-- \"bottom\" (inner most) reducing function\n# |\n# `-- transducible process","category":"page"},{"location":"explanation/glossary/#glossary-rf","page":"Glossary","title":"Reducing step function","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Reducing function or Reducing step (function): A reducing function combines result-so-far with the input. It in a narrow sense is a \"callable\" op of the signature op(::X, ::Y) :: X (or op(::X, ::X) :: X in case for foldxt) or schematically:","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"(textresult-so-far textinput) mapsto textresult-so-far","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"It is the function that can be passed to the classic (non-Transducers.jl) Base.foldl or Base.reduce. It is sometimes referred to as a step or op. In Transducers.jl, next(rf, ::X, ::Y) :: X is used instead of a \"bare\" callable. Furthermore, a reducing function in a loose sense also includes other interfaces such as start(rf, ::X) and complete(rf, ::X).","category":"page"},{"location":"explanation/glossary/#glossary-transducer","page":"Glossary","title":"Transducer","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"A transducer in Transducers.jl is a transformation xf that","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"transforms an iterator with xf(itr) (iterator transformation)\ntransforms a reducing step function with xf'(rf) (reducing function transformation)","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Common variable names for transducers are xf and xform.","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"The idea of generalizing the transducer as two kinds of transformation is due to Jan Weidner @jw3126. See the discussion in JuliaFolds/Transducers.jl#67.","category":"page"},{"location":"explanation/glossary/#glossary-ixf","page":"Glossary","title":"Iterator transformation","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"As of Transducers.jl 0.4.39, the call overload of Transducer is interpreted as an iterator transformation. That is to say, the iterator transformation using Base.Iterators","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"julia> ixf₁ = itr -> Iterators.filter(isodd, itr);","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"and the iterator transformation in Transducers.jl","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"julia> ixf₂ = Filter(isodd);","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"behaves identically:","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"julia> collect(ixf₁(1:10)) == collect(ixf₂(1:10))\ntrue","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Filter(isodd)(1:10) is an eduction.","category":"page"},{"location":"explanation/glossary/#glossary-rfxf","page":"Glossary","title":"Reducing function transformation","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Transducers.jl 0.4.39 also exposes reducing function (RF) transformation with xf'(rf) (adjoint):","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"julia> rf = Filter(isodd)'(+); # equivalent to (acc, x) -> isodd(x) ? acc + x : acc;\n\njulia> rf(0, 2) # `2` filtered out\n0\n\njulia> rf(0, 1) # `1` not filtered out\n1","category":"page"},{"location":"explanation/glossary/#Transducer-in-the-narrow-sense-(Clojure)","page":"Glossary","title":"Transducer in the narrow sense (Clojure)","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"The transducer as originally introduced by Rich Hickey is a transformation of reducing step function. Thus, what is referred to as a transducer mathrmxf in Clojure and many other languages is the reducing function transformation xf' in Transducer.jl.","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Since a transducer in the narrow sense maps a reducing function to a reducing function, it can be composed with simple function composition . When a composite transducer mathrmxf = mathrmxf_1 circ mathrmxf_2 circ circ mathrmxf_n to a \"bottom\" reducing function mathrmrf_0, it is processed from right to left just like normal functions:","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"mathrmrf =\nmathrmxf_1(mathrmxf_2((mathrmxf_n(mathrmrf_0))))","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"which is equivalent to the following forms in Transducers.jl","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"rf = xf₁'(xf₂'(...(xfₙ'(rf₀))))\nrf = (xf₁' ∘ xf₂' ∘ ... ∘ xfₙ')(rf₀)\nrf = (xfₙ ∘ ... ∘ xf₂ ∘ xf₁)'(rf₀)\nrf = (xf₁ ⨟ xf₂ ⨟ ... ⨟ xfₙ)(rf₀)","category":"page"},{"location":"explanation/glossary/#Inner-transducer","page":"Glossary","title":"Inner transducer","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Given a composition xf₁' ∘ xf₂', transducer xf₂ is said to be the inner transducer of xf₁' ∘ xf₂'. Likewise, xf₂'(rf₀) is an inner reducing function of xf₁'(xf₂'(rf₀)).","category":"page"},{"location":"explanation/glossary/#Reducible-collection","page":"Glossary","title":"Reducible collection","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Reducible collection (or just Reducible): Any object that can be passed to foldl and alike is reducible. A reducible collection knows how to apply reducing function to its elements. Iterators are automatically reducible as this is the canonical fallback implementation.","category":"page"},{"location":"explanation/glossary/#Transducible-process","page":"Glossary","title":"Transducible process","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"A function that can foldxt reducible collections using transducers is a transducible process. Examples are foldl and foldxt. Find more in Transducible processes.","category":"page"},{"location":"explanation/glossary/#glossary-executor","page":"Glossary","title":"Executor","text":"","category":"section"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"An executor such as SequentialEx, ThreadedEx and DistributedEx specifies the execution mechanism of a fold. These executors provide a unified mechanism for choosing underlying execution mechanism for Transducers.jl and its related packages such as Folds.jl and FLoops.jl. Typically, the API functions take an executor as the last optional argument. In addition to the executors provided by Transducers.jl (see Executors section in the manual), additional executors are provided from external packages such as FoldsThreads.jl (various thread-based executors) and FoldsCUDA.jl (a CUDA-based executor).","category":"page"},{"location":"explanation/glossary/","page":"Glossary","title":"Glossary","text":"Transducers.jl's executor is a concept similar to KernelAbstractions.jl' device.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"EditURL = \"../../../examples/useful_patterns.jl\"","category":"page"},{"location":"howto/useful_patterns/#Useful-patterns","page":"Useful patterns","title":"Useful patterns","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"This page includes some useful patterns using Transducers.jl.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"using Transducers","category":"page"},{"location":"howto/useful_patterns/#Flattening-nested-objects-using-MapCat","page":"Useful patterns","title":"Flattening nested objects using MapCat","text":"","category":"section"},{"location":"howto/useful_patterns/#Simple-MapCat-usage","page":"Useful patterns","title":"Simple MapCat usage","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Consider a vector of \"objects\" (here just NamedTuples) which in turn contain a vector of objects:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"nested_objects = [\n (a = 1, b = [(c = 2, d = 3), (c = 4, d = 5)]),\n (a = 10, b = [(c = 20, d = 30), (c = 40, d = 50)]),\n];\nnothing #hide","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"We can flatten this into a table by using Map inside MapCat:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"using TypedTables\nastable(xs) = copy(Table, xs) # using `TypedTables` for a nice display\n\ntable1 = nested_objects |> MapCat() do x\n x.b |> Map() do b # not `MapCat`\n (a = x.a, b...)\n end\nend |> astable","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"(Note that the transducer used inside MapCat is Map, not MapCat)","category":"page"},{"location":"howto/useful_patterns/#Nested-MapCat","page":"Useful patterns","title":"Nested MapCat","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"This pattern can handle more nested objects:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"more_nested_objects = [\n (a = 1, b = [(c = 2, d = [(e = 3, f = 4), (e = 4, f = 5)]),\n (c = 6, d = [])]),\n (a = 10, b = [(c = 20, d = [(e = 30, f = 40), (e = 40, f = 50)])]),\n];\nnothing #hide","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"By using nested MapCat (except for the \"inner most\" processing which uses Map since there is nothing to concatenate):","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"table3 =\n more_nested_objects |> MapCat() do x\n x.b |> MapCat() do b\n b.d |> Map() do d\n (a = x.a, c = b.c, d...)\n end\n end\n end |> astable","category":"page"},{"location":"howto/useful_patterns/#Comparison-with-iterator-comprehension","page":"Useful patterns","title":"Comparison with iterator comprehension","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"As a comparison, here is how to do it with iterator comprehension","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"rows = (\n (a = x.a, c = b.c, d...)\n for x in more_nested_objects\n for b in x.b\n for d in b.d\n)\n@assert Table(collect(rows)) == table3","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"For a simple flattening and mapping, iterator comprehension as above perhaps is the simplest solution.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Note that Transducers.jl works well with iterator comprehensions. Transducers.jl-specific entry points like foldxl converts iterator comprehensions to transducers internally. eduction can be used to explicitly do this conversion:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"@assert astable(eduction(rows)) == table3","category":"page"},{"location":"howto/useful_patterns/#Complex-MapCat-example","page":"Useful patterns","title":"Complex MapCat example","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"For more complex processing that requires intermediate variables, the iterator comprehension does not work well. Fortunately, it is easy to use intermediate variables with transducers:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ans = begin # hide\nmore_nested_objects |>\nMapCat() do x\n a2 = x.a * 2\n x.b |> MapCat() do b\n a2_plus_c = a2 + b.c\n b.d |> Map() do d\n c_plus_e = b.c + d.e\n c_plus_f = b.c + d.f\n (a2_plus_c = a2_plus_c, c_plus_e = c_plus_e, c_plus_f = c_plus_f)\n end\n end\nend |>\nastable\nend # hide","category":"page"},{"location":"howto/useful_patterns/#MapCat-with-zip","page":"Useful patterns","title":"MapCat with zip","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Note also that MapCat can be combined with arbitrary iterator combinators such as zip","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ans = begin # hide\n[(a = 1:3, b = 'x':'z'), (a = 1:4, b = 'i':'l')] |>\nMapCat() do x\n zip(x.a, x.b)\nend |>\nMapSplat((a, b) -> (a = a, b = b)) |>\nastable\nend # hide","category":"page"},{"location":"howto/useful_patterns/#MapCat-with-Iterators.product","page":"Useful patterns","title":"MapCat with Iterators.product","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"... and product","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ans = begin # hide\n[(a = 1:3, b = 'x':'z'), (a = 1:4, b = 'i':'l')] |>\nMapCat() do x\n Iterators.product(x.a, x.b)\nend |>\nEnumerate() |>\nFilter(x -> x[1] % 5 == 0) |> # include only every five item\nMapSplat((n, (a, b)) -> (n = n, a = a, b = b)) |>\nastable\nend # hide","category":"page"},{"location":"howto/useful_patterns/#\"Missing-value\"-handling-with-KeepSomething","page":"Useful patterns","title":"\"Missing value\" handling with KeepSomething","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Transducers.jl has a generic filtering such as Filter as well as type-based filtering such as NotA and OfType. These transducers can be used to filter out \"missing values\" represented as missing or nothing.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"KeepSomething is a transducer that is useful for working on Union{Nothing,Some{T}}. It filters out nothing and yield itmes after applying something.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"[nothing, 1, Some(nothing), 2, 3] |> KeepSomething(identity) |> collect","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Thus, KeepSomething works well with any tools that operate on Union{Nothing,Some{T}}. Here is an example of using it with Maybe.jl. Consider a vector of heterogeneous dictionaries with varying set of keys:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"heterogeneous_objects = [\n Dict(:a => 1, :b => Dict(:c => 2)),\n Dict(:a => 1), # missing key\n Dict(:a => 1, :b => Dict()), # missing key\n Dict(:b => Dict(:c => 2)), # missing key\n Dict(:a => 10, :b => Dict(:ccc => 20)), # alternative key name\n];\nnothing #hide","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Using @something and @? macros from Maybe.jl, we can convert this to a regular table quite easily:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"using Maybe\nusing Maybe: @something\n\nans = begin # hide\nheterogeneous_objects |>\nKeepSomething() do x\n c = @something { # (1)\n @? x[:b][:c]; # (2)\n @? x[:b][:ccc]; # (3)\n return; # (4)\n }\n @? (a = x[:a], c = c) # (5)\nend |>\nastable\nend # hide","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"In this example, for each dictionary x, the body of the do block works as follows:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"(1) Try to extract the item c.\n(2) First, try to get it from x[:b][:c].\n(3) If x[:b][:c] doesn't exist, try x[:b][:ccc] next.\n(4) If both x[:b][:c] and x[:b][:ccc] do not exist, return nothing. KeepSomething will filter out this entry.\n(5) Try to extract the item a from x[:a].\nIf this does not exist, the whole expression wrapped by @? evaluates to nothing. This, in turn, will be filtered out by KeepSomething.\nIf x[:a] exists, @? (a = x[:a], c = c) evaluates to Some((a = value_of_a, c = value_of_c)). The Some wrapper is unwrapped by something called by KeepSomething.","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"For more information, see the tutorial in Maybe.jl documentation.","category":"page"},{"location":"howto/useful_patterns/#Multiple-outputs","page":"Useful patterns","title":"Multiple outputs","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Usually, reducers like sum and collect have one output. However we can use TeeRF etc. to \"fan-out\" input items to multiple outputs.","category":"page"},{"location":"howto/useful_patterns/#Multiple-output-vectors","page":"Useful patterns","title":"Multiple output vectors","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Here is an example of creating two output vectors of integers and symbols in one go:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ints, symbols =\n [1, :two, missing, 3, 4, :five, 6] |>\n Filter(!isequal(6)) |>\n foldxl(TeeRF(\n OfType(Int)'(push!!), # push integers to a vector\n OfType(Symbol)'(push!!), # push symbols to a vector\n ))","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Here, we use TeeRF(rf₁, rf₂, ..., rfₙ) to fan-out input items to multiple reducing functions. To compose each reducing function, we use OfType transducer as reducing function transformation xf'(rf).","category":"page"},{"location":"howto/useful_patterns/#Handling-empty-results","page":"Useful patterns","title":"Handling empty results","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Note that fold with push!! throws when the input is empty. To obtain an empty vector when the input is empty or all filtered out, we need to specify init. MicroCollections.jl includes a library of collections useful as init. Here, we can use EmptyVector:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"using MicroCollections\n\nints, strings =\n [1, :two, missing, 3, 4, :five, 6] |>\n Filter(!isequal(6)) |>\n foldxl(TeeRF(\n OfType(Int)'(push!!), # push integers to a vector\n OfType(String)'(push!!), # push strings to a vector (but there is no string)\n ); init = EmptyVector())","category":"page"},{"location":"howto/useful_patterns/#Composed-transducers-with-TeeRF","page":"Useful patterns","title":"Composed transducers with TeeRF","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Each reducing function passed to TeeRF can use arbitrary complex transducers. Here is an example of filtering-in symbols and then map them to strings:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ints, strings =\n [1, :two, missing, 3, 4, :five, 6] |>\n Filter(!isequal(6)) |>\n foldxl(\n TeeRF(\n OfType(Int)'(push!!),\n opcompose(OfType(Symbol), Map(String))'(push!!), # filter _then_ map\n );\n init = EmptyVector(),\n )","category":"page"},{"location":"howto/useful_patterns/#Nested-TeeRF","page":"Useful patterns","title":"Nested TeeRF","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"Each reducing function itself passed to TeeRF can even be composed using TeeRF (or other reducing function combinators; e.g., ProductRF). Here is an example of computing extrema on integers:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"(imin, imax), strings =\n [1, :two, missing, 3, 4, :five, 6] |>\n Filter(!isequal(6)) |>\n foldxl(\n TeeRF(\n OfType(Int)'(TeeRF(max, min)), # extrema on integers\n opcompose(OfType(Symbol), Map(String))'(push!!), # filter _then_ map\n );\n init = ((typemin(Int), typemax(Int)), EmptyVector()),\n )","category":"page"},{"location":"howto/useful_patterns/#When-input-is-a-tuple:-ProductRF","page":"Useful patterns","title":"When input is a tuple: ProductRF","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ProductRF is like TeeRF but it expects that the input is already a tuple:","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ints, io =\n [(1:3, 'x':'z'), nothing, (1:4, 'i':'l')] |>\n NotA(Nothing) |>\n foldxl(\n ProductRF(\n opcompose(Cat(), Filter(isodd))'(push!!), # process 1:3 etc.\n Cat()'((io, char) -> (write(io, char); io)), # process 'x':'z' etc.\n );\n init = (EmptyVector(), IOBuffer()),\n );\nnothing #hide","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"String(take!(io))","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"ints","category":"page"},{"location":"howto/useful_patterns/#When-input-is-a-row:-DataTools.oncol","page":"Useful patterns","title":"When input is a row: DataTools.oncol","text":"","category":"section"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"oncol from DataTools.jl is like ProductRF but acts on NamedTuple (as well as any Accessors.jl-compatible possibly nested objects).","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"using DataTools\nfoldxl(oncol(a = +, b = *), [(a = 1, b = 2), (a = 3, b = 4)])","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"","category":"page"},{"location":"howto/useful_patterns/","page":"Useful patterns","title":"Useful patterns","text":"This page was generated using Literate.jl.","category":"page"},{"location":"parallelism/#overview-parallel","page":"Parallelism","title":"Overview of parallel processing in Transducers.jl","text":"","category":"section"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"Transducers.jl supports thread-based (foldxt) and process-based (foldxd) parallelisms with the same composable API; i.e. transducers. Having a uniform API to cover different parallelisms as well as sequential processing foldl is useful. Using multiple cores or machines for your computation is as easy as replacing foldl with foldxt or foldxd; you don't need to re-write your transducers or reducing functions.","category":"page"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"See also:","category":"page"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"Parallel processing tutorial in Transducers.jl manual.\nAPI documentation of foldxt and foldxd.","category":"page"},{"location":"parallelism/#Thread-based-parallelism","page":"Parallelism","title":"Thread-based parallelism","text":"","category":"section"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"note: Note\nTo use multiple threads, the julia process must be started with appropriate environment variable JULIA_NUM_THREADS. See Julia manual for more information about how to enable and verify multi-threading in Julia:Multi-Threading (Experimental) · Parallel Computing · The Julia Language\nJULIA_NUM_THREADS · Environment Variables · The Julia Language","category":"page"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"Transducers.jl supports thread-based parallelism for Julia ≥ 1.0. You can use it by replacing foldl with foldxt. With Julia ≥ 1.3, Transducers.jl supports early termination to avoid unnecessary computation while guaranteeing the result to be deterministic; i.e., it does not depend on how computation tasks are scheduled.","category":"page"},{"location":"parallelism/#Process-based-parallelism","page":"Parallelism","title":"Process-based parallelism","text":"","category":"section"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"Transducers.jl supports process-based parallelism using Distributed.jl. You can use it by replacing foldl with foldxd. It can be used for horizontally scaling the computation. It is also useful for using external libraries that are not \"thread-safe.\"","category":"page"},{"location":"parallelism/","page":"Parallelism","title":"Parallelism","text":"Note that early termination is not supported in foldxd yet.","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"EditURL = \"../../../examples/reducibles.jl\"","category":"page"},{"location":"howto/reducibles/#How-to-make-your-data-type-reducible","page":"Writing reducibles","title":"How to make your data type reducible","text":"","category":"section"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Let's see how to make a vector-of-vector a reducible collection; i.e., a type that can be fed to foldl.","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"struct VecOfVec{T}\n vectors::Vector{Vector{T}}\nend","category":"page"},{"location":"howto/reducibles/#Method-1:-The-__foldl__-interface:","page":"Writing reducibles","title":"Method 1: The __foldl__ interface:","text":"","category":"section"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"We need @next and complete to invoke the reducing function rf.","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"using Transducers\nusing Transducers: @next, complete","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Supporting foldl and similar only requires Transducers.__foldl__:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"function Transducers.__foldl__(rf, val, vov::VecOfVec)\n for vector in vov.vectors\n for x in vector\n val = @next(rf, val, x)\n end\n end\n return complete(rf, val)\nend","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Note that it's often a good idea to implement Base.eltype:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Base.eltype(::VecOfVec{T}) where {T} = T","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"It can be then used as the input to the transducers:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov = VecOfVec(collect.([1:n for n in 1:3]))\ncollect(Map(identity), vov)","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Macro @next is used instead of function next to avoid the boilerplate for supporting early termination (see the details in in @next documentation). In practice, using @next means that your __foldl__ supports early termination:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov |> Take(3) |> collect","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"More complex example:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov |> PartitionBy(isequal(1)) |> Zip(Map(copy), Map(sum)) |> collect","category":"page"},{"location":"howto/reducibles/#Method-2:-In-terms-of-existing-transducers-and-reducibles-with-asfoldable","page":"Writing reducibles","title":"Method 2: In terms of existing transducers and reducibles with asfoldable","text":"","category":"section"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Transducers.jl has a function Transducers.asfoldable which can be overloaded to convert your existing type into a foldable before being fed into __foldl__. This allows us to express a new type in terms of existing structures:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"struct VecOfVec2{T}\n vectors::Vector{T}\nend\nTransducers.asfoldable(vov::VecOfVec2) = vov.vectors |> Cat()","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"This simply tells Transducers.jl that a VecOfVec2 may be folded over by simply applying the Cat transducer to the .vectors field of the struct. This is enough to reproduce all the examples from the previous section:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov2 = VecOfVec2(collect.([1:n for n in 1:3]))\ncollect(Map(identity), vov2)","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov2 |> Take(3) |> collect","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"vov2 |> PartitionBy(isequal(1)) |> Zip(Map(copy), Map(sum)) |> collect","category":"page"},{"location":"howto/reducibles/#Comparison-to-defining-an-Iterator:","page":"Writing reducibles","title":"Comparison to defining an Iterator:","text":"","category":"section"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"Notice that writing Transducers.__foldl__ is very straightforward comparing to how to define an iterator:","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"function Base.iterate(vov::VecOfVec, state=(1, 1))\n #Iterator `state` is a tuple of an index `i` to `vov.vectors` and an\n #index `j` to `vov.vectors[i]`:\n i, j = state\n #If `i` is larger than the number of items, we are done:\n i > length(vov.vectors) && return nothing\n #If `j` is in bound, we are iterating the same sub-vector:\n vi = vov.vectors[i]\n if j <= length(vi)\n return vi[j], (i, j + 1)\n end\n #Otherwise, find the next non-empty sub-vector and start iterating it:\n for k in i + 1:length(vov.vectors)\n vk = vov.vectors[k]\n if !isempty(vk)\n return vk[1], (k, 2) # i=k, j=2\n end\n end\n return nothing\nend\n\nBase.length(vov::VecOfVec) = sum(length, vov.vectors)\n\ncollect(vov)","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"","category":"page"},{"location":"howto/reducibles/","page":"Writing reducibles","title":"Writing reducibles","text":"This page was generated using Literate.jl.","category":"page"},{"location":"explanation/comparison_to_iterators/#comparison-to-iterators","page":"Comparison to iterators","title":"Comparison to iterators","text":"","category":"section"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"DocTestSetup = quote\n using Transducers\nend","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"How foldl is used illustrates the difference between iterators and transducers. Consider a transducer","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"julia> using Transducers\n\njulia> xf = opcompose(Filter(iseven), Map(x -> 2x));","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"which works as","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"julia> collect(xf, 1:6)\n3-element Vector{Int64}:\n 4\n 8\n 12\n\njulia> foldl(+, xf, 1:6) # 4 + 8 + 12\n24","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"Implementation of the above computation in iterator would be:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"f(x) = 2x\nimap = Base.Iterators.Generator # like `map`, but returns an iterator\nmapfoldl(f, +, filter(iseven, input), init=0)\nfoldl(+, imap(f, filter(iseven, input))) # equivalent\n# ______________________________\n# composition occurs at input part","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"Compare it to how transducers are used:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"foldl(+, opcompose(Filter(iseven), Map(f)), input, init=0)\n# _________________________________\n# composition occurs at computation part","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"Although this is just a syntactic difference, it is reflected in the actual code generated by those two frameworks. The code for iterator would be lowered to:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"function map_filter_iterators(xs, init)\n ret = iterate(xs)\n ret === nothing && return init\n acc = init\n @goto filter\n local state, x\n while true\n while true # input\n ret = iterate(xs, state) #\n ret === nothing && return acc #\n @label filter #\n x, state = ret #\n iseven(x) && break # filter :\n end # :\n y = 2x # imap : :\n acc += y # + : : :\n end # : : : :\n # + <-- imap <-------- filter <-- input\nend","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"Notice that the iteration of input is the inner most block, followed by filter, imap, and then finally +. Iterators are described as pull-based; an outer iterator (say imap) has to \"pull\" an item from the inner iterator (filter in above example). It is reflected in the lowered code above.","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"On the other hand, the code using transducers is lowered to:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"function map_filter_transducers(xs, init)\n acc = init\n # input -> Filter --> Map --> +\n for x in xs # input : : :\n if iseven(x) # Filter : :\n y = 2x # Map :\n acc += y # +\n end\n end\n return acc\nend\n\nxs = [6, 8, 1, 4, 5, 6, 6, 7, 9, 9, 7, 8, 6, 8, 2, 5, 2, 4, 3, 7]\n@assert map_filter_iterators(xs, 0) == map_filter_transducers(xs, 0)","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"Notice that the iteration of input is at the outer most block while + is in the inner most block. Transducers passed to foldl appears in the block between them in the order they are composed. An outer transducer (say Filter) \"pushes\" arbitrary number of items to the inner transducer (Map in above example). Note that Filter can choose to not push an item (i.e., push zero item) when the predicate returns false. This push-based nature of the transducers allows the generation of very natural and efficient code. To put it another way, the transducers and transducible processes own the loop.","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"As a consequence, computations requiring to expand an item into a sequence can be processed efficiently. Consider the following example:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"julia> xf = opcompose(Map(x -> 1:x), Filter(iseven ∘ sum), Cat())\n foldl(*, xf, 1:10)\n29262643200","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"This is lowered to a nested for loops:","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"function map_filter_cat_transducers(xs, init)\n acc = init\n for x in xs\n y1 = 1:x # Map\n if iseven(sum(y1)) # Filter\n for y2 in y1 # Cat\n acc *= y2 # *\n end\n end\n end\n return acc\nend\n\n@assert foldl(*, xf, 1:10) == map_filter_cat_transducers(1:10, 1)","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"It is not straightforward to implement an iterator like Cat that can output more than one items at a time. Such an iterator has to track the state of the inner (y1 in above) and outer (xs in above) iterators and conditionally invoke the outer iterator once the inner iterator terminates. This generates a complicated code and the compiler would have hard time optimizing it.","category":"page"},{"location":"explanation/comparison_to_iterators/","page":"Comparison to iterators","title":"Comparison to iterators","text":"DocTestSetup = nothing","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"EditURL = \"../../../examples/transducers.jl\"","category":"page"},{"location":"howto/transducers/#How-to-write-transducers","page":"Writing transducers","title":"How to write transducers","text":"","category":"section"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Transducers don't export public interface for implementing transducers (and reducible collections). Let's import some handy ones:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"using Transducers\nusing Transducers: Transducer, R_, next, inner, xform","category":"page"},{"location":"howto/transducers/#Stateless-transducer","page":"Writing transducers","title":"Stateless transducer","text":"","category":"section"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Let's write manually what opcompose(Filter(x -> x isa Int), Map(x -> x + 1)) would do:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"struct AddOneIfInt <: Transducer end\n\nfunction Transducers.next(rf::R_{AddOneIfInt}, result, input)\n if input isa Int\n #Output `input + 1` is passed to the \"inner\" reducing step:\n next(inner(rf), result, input + 1)\n else\n #Filtering out is done by \"doing nothing\"; return `result`-so-far\n #as-is:\n result\n end\nend","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Ineed, for integer collection, it increments input by one:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"addone_out1 = begin # hide\ncollect(AddOneIfInt(), 1:5)\nend # hide","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Non integer elements are filtered out:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"collect(AddOneIfInt(), Any[3, nothing, 2.0, missing, 5])","category":"page"},{"location":"howto/transducers/#Stateful-transducer","page":"Writing transducers","title":"Stateful transducer","text":"","category":"section"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"AddOneIfInt is a stateless transducer which is very easy to implement. A stateful transducer needs a bit more code.","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"using Transducers: start, complete, wrap, unwrap, wrapping\nusing Random","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Let's define a transducer that spits out a random past element from the buffer:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"struct RandomRecall <: Transducer\n history::Int\n seed::Int\nend\nRandomRecall() = RandomRecall(3, 0)\nnothing # hide","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"A stateful transducer needs to implement Transducers.start to \"allocate\" its private state. Here, the private state is a buffer and a random number generator state rng:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"function Transducers.start(rf::R_{RandomRecall}, result)\n buffer = []\n rng = MersenneTwister(xform(rf).seed)\n private_state = (buffer, rng)\n return wrap(rf, private_state, start(inner(rf), result))\nend","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Stateful transducer needs to unwrap its private state inside Transducers.next and then re-wrap it. There is a helper function Transducers.wrapping does that with the do block:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"function Transducers.next(rf::R_{RandomRecall}, result, input)\n wrapping(rf, result) do (buffer, rng), iresult\n #Pickup a random element to be passed to the inner reducing function.\n #Replace it with the new incoming one in the buffer:\n if length(buffer) < xform(rf).history\n push!(buffer, input)\n iinput = rand(rng, buffer)\n else\n i = rand(rng, 1:length(buffer))\n iinput = buffer[i]\n buffer[i] = input\n end\n #Call the inner reducing function. Note that `iresult` unwrapped by\n iresult = next(inner(rf), iresult, iinput)\n return (buffer, rng), iresult\n end\nend","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"(Transducers.wrapping must be passed to next.)","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Any transducer with custom Transducers.start must have a corresponding Transducers.complete. It is responsible for unwrapping the result and call the complete for the inner reducing function.","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"function Transducers.complete(rf::R_{RandomRecall}, result)\n _private_state, inner_result = unwrap(rf, result)\n return complete(inner(rf), inner_result)\nend","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Here is how it works:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"recall_out1 = begin # hide\ncollect(RandomRecall(), 1:5)\nend # hide","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Indeed, it picks up some random elements from the past elements. With slightly more complex transducer:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"1:100 |> Filter(isodd) |> RandomRecall() |> Filter(x -> x > 10) |> Take(5) |> collect","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"Note that Transducers.complete can do more than unwrap and complete. It is useful for, e.g., flushing the buffer.","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"function Transducers.complete(rf::R_{RandomRecall}, result)\n (buffer, _), iresult = unwrap(rf, result)\n for x in buffer\n #Note that inner `next` can be called more than one time inside\n #`next` and `complete`:\n iresult = next(inner(rf), iresult, x)\n end\n #`complete` for inner reducing function must be called exactly once:\n return complete(inner(rf), iresult)\nend","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"This then adds 3 (= RandomRecall().history) more elements to the output:","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"recall_out2 = begin # hide\ncollect(RandomRecall(), 1:5)\nend # hide","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"","category":"page"},{"location":"howto/transducers/","page":"Writing transducers","title":"Writing transducers","text":"This page was generated using Literate.jl.","category":"page"},{"location":"explanation/internals/#Internals","page":"Internals","title":"Internals","text":"","category":"section"},{"location":"explanation/internals/","page":"Internals","title":"Internals","text":"Modules = [Transducers]\nPublic = false\nFilter = Transducers.is_internal","category":"page"},{"location":"explanation/internals/#Transducers.DefaultInit","page":"Internals","title":"Transducers.DefaultInit","text":"DefaultInit(op)\n\nDefaultInit is like Init but strictly internal to Transducers.jl. It is used for checking if the bottom reducing function is never called.\n\n\n\n\n\n","category":"constant"},{"location":"explanation/internals/#Transducers.AdHocRF","page":"Internals","title":"Transducers.AdHocRF","text":"AdHocRF(next; oninit, start = identity, complete = identity, combine = next)\n\nDefine an ad-hoc reducing function rf.\n\nnote: Note\nUse wheninit etc. instead of this constructor.\n\nArguments\n\nnext: binary function\n\nKeyword Arguments\n\noninit: nullary function that generates an initial value for next\nstart: unary function that pre-process the initial value for next\ncomplete: unary function that post-process the accumulator\ncombine: (approximately) associative binary function for combining multiple results of next (before post-processed by complete).\n\nExamples\n\njulia> using Transducers\n using Transducers: AdHocRF\n\njulia> rf = AdHocRF(push!, combine = append!);\n\njulia> foldxt(rf, Map(identity), 1:4; basesize = 1, init = OnInit(() -> []))\n4-element Vector{Any}:\n 1\n 2\n 3\n 4\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers.AdHocXF","page":"Internals","title":"Transducers.AdHocXF","text":"AdHocXF(f, init, [onlast])\n\nExamples\n\njulia> using Transducers\n\njulia> using Transducers: AdHocXF, @next\n\njulia> using Accessors: @reset\n\njulia> flushlast(rf, result) = rf(@next(rf, result, result.state));\n\njulia> xf = AdHocXF(nothing, flushlast) do rf, result, input\n m = match(r\"^name:(.*)\", input)\n if m === nothing\n push!(result.state.lines, input)\n return result\n else\n chunk = result.state\n @reset result.state = (name=strip(m.captures[1]), lines=String[])\n push!(result.state.lines, input)\n if chunk === nothing\n return result\n else\n return rf(result, chunk)\n end\n end\n end;\n\njulia> collect(xf, split(\"\"\"\n name: Map\n type: onetoone\n name: Cat\n type: expansive\n name: Filter\n type: contractive\n name: Cat |> Filter\n type: chaotic\n \"\"\", \"\\n\"; keepempty=false))\n4-element Vector{@NamedTuple{name::SubString{String}, lines::Vector{String}}}:\n (name = \"Map\", lines = [\"name: Map\", \"type: onetoone\"])\n (name = \"Cat\", lines = [\"name: Cat\", \"type: expansive\"])\n (name = \"Filter\", lines = [\"name: Filter\", \"type: contractive\"])\n (name = \"Cat |> Filter\", lines = [\"name: Cat |> Filter\", \"type: chaotic\"])\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers.NoAdjoint","page":"Internals","title":"Transducers.NoAdjoint","text":"Transducers.NoAdjoint(itr)\n\nBypass the optimization step by retransform.\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers.ReduceSplitBy","page":"Internals","title":"Transducers.ReduceSplitBy","text":"Transducers.ReduceSplitBy(f, rf, init)\n\nSplit chunks by elements evaluated to true by f and reduce each chunk by reducing function rf.\n\nnote: Note\nThis is an internal implementation detail of SplitBy for now.\n\nThe reducing function rf receives either a Bulk(x) if !f(x) or a End(x) if f(x) returns true. Just just after rf is called with End(x), its accumulator is finalized by complete and then passed to the downstream transducer/reducing function.\n\nExamples\n\njulia> using Transducers\n using Transducers: ReduceSplitBy, Bulk, End\n\njulia> 1:5 |> ReduceSplitBy(isodd, Map(getindex)'(string), \"\") |> collect\n3-element Vector{String}:\n \"1\"\n \"23\"\n \"45\"\n\njulia> function just_bulk(x)\n if x isa Bulk\n Some(x[])\n else\n nothing\n end\n end;\n\njulia> 1:5 |> ReduceSplitBy(isodd, KeepSomething(just_bulk)'(string), \"\") |> collect\n3-element Vector{String}:\n \"\"\n \"2\"\n \"4\"\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers.ReducingFunctionTransform","page":"Internals","title":"Transducers.ReducingFunctionTransform","text":"ReducingFunctionTransform(xf)\n\nThe \"true\" transducer.\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers.UseSIMD","page":"Internals","title":"Transducers.UseSIMD","text":"UseSIMD{ivdep}()\n\nTell the reducible to run the inner reducing function using @simd. The reducible can support it using @simd_if.\n\n\n\n\n\n","category":"type"},{"location":"explanation/internals/#Transducers._set_joiner_value-Tuple{Any, Any}","page":"Internals","title":"Transducers._set_joiner_value","text":"_set_joiner_value(ps::PrivateState, x) :: PrivateState\n\nSet .state field of the PrivateState of the first \"unbalanced\" Joiner. A Joiner matched with preceding Splitter would be treated as a regular reducing function node. Thus, private state ps must have one more Joiner than Splitter.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers._unzip-Union{Tuple{Tuple{Vararg{Tuple{Vararg{Any, N}}}}}, Tuple{N}} where N","page":"Internals","title":"Transducers._unzip","text":"_unzip(xs::Tuple)\n\nExamples\n\njulia> _unzip(((1, 2, 3), (4, 5, 6)))\n((1, 4), (2, 5), (3, 6))\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.air-Tuple{Any}","page":"Internals","title":"Transducers.air","text":"air.(broadcasting_expression) :: Broadcasted\n\nBroadcast without materialization.\n\nThe idea is taken from @dawbarton's _lazy function: https://discourse.julialang.org/t/19641/20.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.asfoldable-Tuple{Any}","page":"Internals","title":"Transducers.asfoldable","text":"Transducers.asfoldable(x) -> foldable\n\nBy default, this function does nothing, but it can be overloaded to convert an input into another type before reducing over it. This allows one to implement a foldable in terms of transducers over an existing type. For instance,\n\nstruct VectorOfVectors{T}\n v::Vector{Vector{T}}\nend\n\nTransducers.asfoldable(vov::VectorOfVectors{T}) = vov.v |> Cat()\n\nNow we can do things like\n\njulia> foldxl(+, VectorOfVectors([[1,2], [3, 4]]))\n10\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.combine-Tuple{Any, Any, Any}","page":"Internals","title":"Transducers.combine","text":"Transducers.combine(rf::R_{X}, state_left, state_right)\n\nThis is an optional interface for a transducer. If transducer X is stateful (i.e., wrap is used in start), it has to be able to combine the private states to support fold functions that require an associative reducing function such as foldxt. Typical implementation takes the following form:\n\nfunction combine(rf::R_{X}, a, b)\n # ,---- `ua` and `ub` are the private state of the transducer `X`\n # / ,-- `ira` and `irb` are the states of inner reducing functions\n # / /\n ua, ira = unwrap(rf, a)\n ub, irb = unwrap(rf, b)\n irc = combine(inner(rf), ira, irb)\n uc = # somehow combine private states `ua` and `ub`\n return wrap(rf, uc, irc)\nend\n\nSee ScanEmit, etc. for real-world examples.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.completebasecase-Tuple{Any, Any}","page":"Internals","title":"Transducers.completebasecase","text":"Transducers.completebasecase(rf, state)\n\nProcess basecase result state before merged by combine.\n\nFor example, on GPU, this function can be used to translate mutable states to immutable values for exchanging them through (un-GC-managed) memory. See whencompletebasecase.\n\nnote: Note\nThis function is an internal experimental interface for FoldsCUDA.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.extract_transducer-Tuple{Any}","page":"Internals","title":"Transducers.extract_transducer","text":"extract_transducer(foldable) -> (xf, foldable′)\n\n\"Reverse\" of eduction.\n\nExamples\n\njulia> using Transducers\n\njulia> double(x) = 2x;\n\njulia> xs = 1:10;\n\njulia> xf, foldable = Transducers.extract_transducer(Iterators.map(double, xs));\n\njulia> xf == Map(double)\ntrue\n\njulia> foldable == xs\ntrue\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.foldl_basecase-Union{Tuple{RF}, Tuple{RF, Any, Any}} where RF","page":"Internals","title":"Transducers.foldl_basecase","text":"foldl_basecase(rf, init, coll)\n\nfoldl for basecase of parallel reduction. Call __foldl__ without calling complete and then call completebasecase.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.foldl_nocomplete-Union{Tuple{RF}, Tuple{RF, Any, Any}} where RF","page":"Internals","title":"Transducers.foldl_nocomplete","text":"foldl_nocomplete(rf, init, coll)\n\nCall __foldl__ without calling complete.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.initialize-Tuple{Any, Any}","page":"Internals","title":"Transducers.initialize","text":"initialize(initializer, op) -> init\ninitialize(init, _) -> init\n\nReturn an initial value for op. Throw an error if initializer (e.g., Init) creates unknown initial value.\n\nExamples\n\njulia> using Transducers\n using Transducers: initialize\n\njulia> initialize(Init, +)\nInitialValue(+)\n\njulia> initialize(123, +)\n123\n\njulia> unknown_op(x, y) = x + 2y;\n\njulia> initialize(Init, unknown_op)\nERROR: IdentityNotDefinedError: `init = Init` is specified but the identity element `InitialValue(op)` is not defined for\n op = unknown_op\n[...]\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.initvalue-Tuple{Any}","page":"Internals","title":"Transducers.initvalue","text":"initvalue(initializer::AbstractInitializer) -> init\ninitvalue(init) -> init\n\nMaterialize the initial value if the input is an AbstractInitializer. Return the input as-is if not.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.is_prelude","page":"Internals","title":"Transducers.is_prelude","text":"is_prelude(::T)\n\nReturn true if it is better to tail-call when the accumulator or the private state changes its type from T.\n\n\n\n\n\n","category":"function"},{"location":"explanation/internals/#Transducers.issmall","page":"Internals","title":"Transducers.issmall","text":"Transducers.issmall(reducible, basesize) :: Bool\n\nCheck if reducible collection is considered small compared to basesize (an integer). Fold functions such as foldxt switches to sequential __foldl__ when issmall returns true.\n\nDefault implementation is amount(reducible) <= basesize.\n\n\n\n\n\n","category":"function"},{"location":"explanation/internals/#Transducers.maybe_usesimd-Tuple{Transducers.AbstractReduction, Union{Val{true}, Val{false}, Val{:ivdep}, Bool, Symbol}}","page":"Internals","title":"Transducers.maybe_usesimd","text":"maybe_usesimd(xform, simd)\n\nInsert UseSIMD to xform if appropriate.\n\nArguments\n\nxform::Transducer\nsimd: false, true, or :ivdep.\n\nExamples\n\njulia> using Transducers\n using Transducers: maybe_usesimd\n\njulia> maybe_usesimd(reducingfunction(Map(identity), right), false)\nReduction(\n Map(identity),\n BottomRF(\n Transducers.right))\n\njulia> maybe_usesimd(reducingfunction(Map(identity), right), true)\nReduction(\n Transducers.UseSIMD{false}(),\n Reduction(\n Map(identity),\n BottomRF(\n Transducers.right)))\n\njulia> maybe_usesimd(reducingfunction(Cat(), right), true)\nReduction(\n Cat(),\n Reduction(\n Transducers.UseSIMD{false}(),\n BottomRF(\n Transducers.right)))\n\njulia> maybe_usesimd(opcompose(Map(sin), Cat(), Map(cos))'(right), :ivdep)\nReduction(\n Map(sin),\n Reduction(\n Cat(),\n Reduction(\n Transducers.UseSIMD{true}(),\n Reduction(\n Map(cos),\n BottomRF(\n Transducers.right)))))\n\njulia> maybe_usesimd(\n opcompose(Map(sin), Cat(), Map(cos), Cat(), Map(tan))'(right),\n true,\n )\nReduction(\n Map(sin),\n Reduction(\n Cat(),\n Reduction(\n Map(cos),\n Reduction(\n Cat(),\n Reduction(\n Transducers.UseSIMD{false}(),\n Reduction(\n Map(tan),\n BottomRF(\n Transducers.right)))))))\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.reform-Tuple{Transducers.Reduction, Any}","page":"Internals","title":"Transducers.reform","text":"reform(rf, f)\n\nReset \"bottom\" reducing function of rf to f.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.retransform-Tuple{Any, Any}","page":"Internals","title":"Transducers.retransform","text":"Transducers.retransform(rf, itr) -> rf′, itr′\n\nExtract transformations in rf and itr and use the appropriate adjoint for better performance.\n\nNote that the reducing function extracted from a comprehension such as (f(x) for x ∈ itr) may not be == to f because of the way generator comprehensions work in Julia. Use Iterators.map to specify an exact mapping function.\n\nExamples\n\njulia> using Transducers\n\njulia> double(x) = 2x;\n\njulia> itr0 = 1:10;\n\njulia> itr1 = Iterators.map(double, itr0);\n\njulia> rf, itr2 = Transducers.retransform(+, itr1);\n\njulia> itr2 === itr0\ntrue\n\njulia> rf == reducingfunction(Map(double), +)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.simple_transduce-NTuple{4, Any}","page":"Internals","title":"Transducers.simple_transduce","text":"simple_transduce(xform, step, init, coll)\n\nSimplified version of transduce. For simple transducers Julia may be able to emit a good code. This function exists only for performance tuning.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.usesimd-Tuple{Transducers.AbstractReduction, Transducers.UseSIMD}","page":"Internals","title":"Transducers.usesimd","text":"usesimd(rf::Reduction, xfsimd::UseSIMD)\n\nWrap the inner-most loop of reducing function rf with xfsimd. xfsimd is inserted after the inner-most Cat if rf includes Cat.\n\n\n\n\n\n","category":"method"},{"location":"explanation/internals/#Transducers.whencompletebasecase","page":"Internals","title":"Transducers.whencompletebasecase","text":"whencompletebasecase(completebasecase, rf) -> rf′\nwhencompletebasecase(completebasecase) -> rf -> rf′\n\nAdd completebasecase protocol to arbitrary reducing function.\n\nThe function completebasecase is used as follows in the basecase implementation of reduce as follows:\n\ninit′ = oninit()\nacc = start(init′)\nfor x in collection\n acc += rf(acc, x)\nend\nresult = completebasecase(acc)\nreturn result\n\nThe result₁ from basecase 1 and result₂ from basecase 2 are combined using combine protocol:\n\ncombine(result₁, result₂)\n\nnote: Note\nThis function is an internal experimental interface for FoldsCUDA.\n\n\n\n\n\n","category":"function"},{"location":"explanation/internals/#Transducers.@default_finaltype-Tuple{Any, Any}","page":"Internals","title":"Transducers.@default_finaltype","text":"@default_finaltype(xf::Transducer, coll)\n\nInfer the type of the object that would be fed into the second argument input of the bottom reducing function rf(acc, input).\n\nSee: Base.@default_eltype\n\n\n\n\n\n","category":"macro"},{"location":"explanation/internals/#Transducers.@simd_if-Tuple{Any, Any}","page":"Internals","title":"Transducers.@simd_if","text":"@simd_if rf for ... end\n\nWrap for-loop with @simd if the outer most transducer of the reducing function rf is UseSIMD.\n\n\n\n\n\n","category":"macro"},{"location":"explanation/internals/#Transducers.@~-Tuple{Any}","page":"Internals","title":"Transducers.@~","text":"(@~ broadcasting_expression) :: Broadcasted\n\n\n\n\n\n","category":"macro"},{"location":"explanation/internals/","page":"Internals","title":"Internals","text":"Modules = [Transducers.AutoObjectsReStacker]","category":"page"},{"location":"explanation/internals/#Transducers.AutoObjectsReStacker.restack","page":"Internals","title":"Transducers.AutoObjectsReStacker.restack","text":"restack(x) -> x\n\nAn identity function in the sense restack(x) === x. However, it (recursively) re-construct x to beg the compiler to move everything in the stack.\n\n\n\n\n\n","category":"function"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"EditURL = \"../../../examples/tutorial_missings.jl\"","category":"page"},{"location":"tutorials/tutorial_missings/#Tutorial:-missing-value-handling","page":"Tutorial: Missing values","title":"Tutorial: missing value handling","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"This tutorial illustrates the usage of Transducers.jl by stepping through various handling of missing values.","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"using Transducers","category":"page"},{"location":"tutorials/tutorial_missings/#Dot-product","page":"Tutorial: Missing values","title":"Dot product","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Here is a simple way to compute a dot product using MapSplat:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"zip(1:3, 10:2:14) |> MapSplat(*) |> sum","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Let's see what it does step by step. First we create a \"printer\" transducer using the following function (see Map):","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xf_printer(label) = Map() do x\n println(label, \": \", x)\n return x # just return it as-is\nend\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"This transducer just pass-through the input while printing its value (prefixed by a label). Let's sandwich the previous MapSplat(*) with it:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"zip(1:3, 10:2:14) |>\nxf_printer(\" input\") |>\nMapSplat(*) |>\nxf_printer(\"output\") |>\nsum\nflush(stdout) # hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"You can see that the input tuple (1, 10) is splatted into function * by MapSplat which then outputs 10. This is repeated for all inputs.","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Perhaps unfortunately, this way of computing a dot product propagates any missing values contained in the input arrays to the result (which may actually be desired in certain cases).","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xs = [1, missing, 3, 2]\nys = [10, 14, missing, 12]\nzip(xs, ys) |> MapSplat(*) |> sum","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"However, it is very simple to ignore any missing values using OfType:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"zip(xs, ys) |> OfType(Tuple{Vararg{Number}}) |> MapSplat(*) |> sum","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Here, Tuple{Vararg{Number}} is a type that matches with a tuple of any length with numbers. It does not match with a tuple if it has a missing.","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"@assert (1, 0.5) isa Tuple{Vararg{Number}}\n@assert (1, 0.5, 2im) isa Tuple{Vararg{Number}}\n@assert !((1, missing) isa Tuple{Vararg{Number}})","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"The part ... |> OfType(Tuple{Vararg{Number}}) |> MapSplat(*) can be factored out using opcompose:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xf_mdot = opcompose(OfType(Tuple{Vararg{Number}}), MapSplat(*));\nnothing #hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"or equivalently","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"OfType(Tuple{Vararg{Number}}) ⨟ MapSplat(*)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"The transducer xf_mdot can be used where previously OfType(Tuple{Vararg{Number}}) |> MapSplat(*) was used:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"zip(xs, ys) |> xf_mdot |> sum","category":"page"},{"location":"tutorials/tutorial_missings/#Covariance","page":"Tutorial: Missing values","title":"Covariance","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Transducer xf_mdot above can also be used to compute the covariance. First, we need the number of pairs of elements in xs and ys that both of them are not missing:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"nonmissings = zip(xs, ys) |> Map(x -> x isa Tuple{Vararg{Number}}) |> count","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Finally, we have to pre-process the input to xf_mdot by subtracting the average. It's easy to do this with Map:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"using Statistics: mean\n\nfunction xf_demean(xs, ys)\n xmean = mean(skipmissing(xs))\n ymean = mean(skipmissing(ys))\n return Map(((x, y),) -> (x - xmean, y - ymean))\nend\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"We can then compute the covariance by combining xf_demean and xf_mdot:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"s = zip(xs, ys) |> xf_demean(xs, ys) |> xf_mdot |> sum\ns / nonmissings","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"In xf_demean, the averages of the vectors xs and ys are computed separately. It is also easy to compute the averages of the elements where both xs and ys are non-missing:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"function xf_demean2(xs, ys)\n n, xsum, ysum =\n zip(xs, ys) |>\n OfType(Tuple{Vararg{Number}}) |>\n Map(((x, y),) -> (1, x, y)) |>\n Broadcasting() |>\n sum\n xmean = xsum / n\n ymean = ysum / n\n return Map(((x, y),) -> (x - xmean, y - ymean))\nend\n\ns = zip(xs, ys) |> xf_demean2(xs, ys) |> xf_mdot |> sum\ns / nonmissings","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"In xf_demean2, we used Broadcasting transducer to broadcast elements of the tuple (1, x, y) over the reducing function of sum (i.e., +).","category":"page"},{"location":"tutorials/tutorial_missings/#Advanced:-TeeRF-and-ProductRF","page":"Tutorial: Missing values","title":"Advanced: TeeRF and ProductRF","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Alternatively, it can also be computed using by combining foldxl, ProductRF, TeeRF, and DataTools.inc1 (see below for how TeeRF and ProductRF work):","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"using DataTools: inc1\n\nfunction xf_demean3(xs, ys)\n n, (xsum, ysum) =\n zip(xs, ys) |>\n OfType(Tuple{Vararg{Number}}) |>\n foldxl(TeeRF(inc1, ProductRF(+, +)))\n xmean = xsum / n\n ymean = ysum / n\n return Map(((x, y),) -> (x - xmean, y - ymean))\nend\n\ns = zip(xs, ys) |> xf_demean3(xs, ys) |> xf_mdot |> sum\ns / nonmissings","category":"page"},{"location":"tutorials/tutorial_missings/#Vectorized-reduction","page":"Tutorial: Missing values","title":"Vectorized reduction","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"reduce, sum, etc. in Base support dims argument. Transducers.jl does not support this argument as of writing. However, this can easily be emulated using eachcol, eachrow, or eachslice iterators in Base.","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xs = [\n 0 missing 1 2\n 3 4 5 missing\n missing 6 7 missing\n]\n\nif VERSION < v\"1.1\"\n using Compat: eachcol\nend\neachcol(xs) |> Broadcasting() |> NotA(Missing) |> sum","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Here, we use NotA transducer that filters out missing values:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 2, missing, 3] |> NotA(Missing) |> collect","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Above computation returns the sum over each row without taking into account the relationship within a column. Another possibly useful reduction is the sum of the columns with no missing values. This can easily be done by filtering before:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"eachcol(xs) |> Filter(x -> !any(ismissing, x)) |> Broadcasting() |> sum","category":"page"},{"location":"tutorials/tutorial_missings/#findmax-and-findmin","page":"Tutorial: Missing values","title":"findmax and findmin","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Another useful operation is findmax/findmin. Using Filter, missing values can be filtered out by","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"filtered_pairs = [1, 3, missing, 0] |> pairs |> Filter(!(ismissing ∘ last))\ncollect(filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"These key-value pairs can be accumulated by the following reducing step function:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"# ,--- current state\n# |\n# | ,-- input\n# | |\nfunction findmax_step((argmax, max), (index, value))\n argmax, max = value > max ? (index, value) : (argmax, max)\n return argmax => max\n # \\\n # \\__ next state\nend\n\nfoldxl(findmax_step, filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"or equivalently","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 3, missing, 0] |> pairs |> Filter(!(ismissing ∘ last)) |> foldxl(findmax_step)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldxl is like foldl but always uses Transducers.jl's extended fold protocol. It also has the unary curried method foldxl(rf) defined as xs -> foldxl(rf, xs). It is handy to use in the piping context as in the latter example.","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"DataTools.rightif can be used for defining findmax/findmin-like functions on the fly:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"using DataTools: rightif\n\nfoldxl(rightif(<, last), filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/#Side-note:-why-Pair{Int,Union{Missing,Int}}?","page":"Tutorial: Missing values","title":"Side note: why Pair{Int,Union{Missing,Int}}?","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"The result type just above using rightif is Pair{Int,Union{Missing,Int}}:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"typeof(foldxl(rightif(<, last), filtered_pairs))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"This is because that's the element type of pairs([1, 3, missing, 0]) and rightif does not re-construct the input Pair like findmax_step:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 3, missing, 0] |> pairs |> first |> typeof","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"We can avoid this by pre-processing the input with MapSplat(Pair):","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldxl(rightif(<, last), filtered_pairs |> MapSplat(Pair))","category":"page"},{"location":"tutorials/tutorial_missings/#findmin","page":"Tutorial: Missing values","title":"findmin","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Similarly, we can define findmin with","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"function findmin_step((argmin, min), (index, value))\n argmin, min = value < min ? (index, value) : (argmin, min)\n return argmin => min\nend\n\nfoldxl(findmin_step, filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"and","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldxl(rightif(>, last), filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/#tutorial-findminmax","page":"Tutorial: Missing values","title":"Extrema (findminmax)","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"To compute findmax and findmax in a single sweep, we can use TeeRF to \"fan out\" the input stream to multiple reducing step functions:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldxl(TeeRF(findmin_step, findmax_step), filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"or equivalently","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldxl(TeeRF(rightif(>, last), rightif(<, last)), filtered_pairs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"In general, multiple folds on a same collection","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"a₁ = foldxl(rf₁, xs)\na₂ = foldxl(rf₂, xs)\n...\naₙ = foldxl(rfₙ, xs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"can be fused into a single fold using TeeRF","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"a₁, a₂, ..., aₙ = foldxl(TeeRF(rf₁, rf₂, ..., rfₙ), xs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"provided that the input collection xs and the reducing functions rf₁, rf₂, ..., and rfₙ are not stateful.","category":"page"},{"location":"tutorials/tutorial_missings/#More-fusing-by-transforming-reducing-functions","page":"Tutorial: Missing values","title":"More fusing by transforming reducing functions","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"In the above computation, we have a reducing (step) function","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"rf = TeeRF(rightif(>, last), rightif(<, last));\nnothing #hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"a transducer","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xf = Filter(!(ismissing ∘ last));\nnothing #hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"and an iterable","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"xs = pairs([1, 3, missing, 0]);\nnothing #hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"In Transducers.jl, a transducer acts as iterator transformation xf(xs) as well as reducing function transformation xf'(rf). Thus, the following calls are equivalent:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"if VERSION >= v\"1.3\" # hide\n@assert foldxl(rf, xf, xs) == (4 => 0, 2 => 3)\n@assert foldxl(rf, xf(xs)) == (4 => 0, 2 => 3)\n@assert foldxl(xf'(rf), xs) == (4 => 0, 2 => 3)\nend # hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"By exploiting this equality, we can fuse more computations by moving the transformation on the side of reducing function. For example, we can compute non-missing extrema and count missings at the same time:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 3, missing, 0] |>\npairs |>\nMapSplat(Pair) |> # avoid `Pair{Int,Union{Missing, Int}}`\nfoldxl(TeeRF(\n Map(ismissing ∘ last)'(+), # count number of missings\n Filter(!(ismissing ∘ last))'(TeeRF(\n rightif(>, last), # find non-missing minimum\n rightif(<, last), # find non-missing maximum\n )),\n))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Using ProductRF, we can compute findmax of individual and zipped items at the same time","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"zip(\n pairs([1, 3, missing, 0]), # produces k1 => v1\n pairs([4, missing, 6, 5]), # produces k2 => v2\n) |>\nMap() do ((k1, v1), (k2, v2))\n (k1 => v1, k2 => v2, (k1, k2) => (v1, v2))\nend |>\nfoldxl(ProductRF(\n Filter(!(ismissing ∘ last))'(rightif(<, last)), # max of k1 => v1\n Filter(!(ismissing ∘ last))'(rightif(<, last)), # max of k2 => v2\n Filter(((_, (v1, v2)),) -> v1 !== missing && v2 !== missing)'(\n rightif(<, last) # max (k1, k2) => (v1, v2)\n ),\n))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"ProductRF is like TeeRF but acts on the input that is already a tuple. That is to say, given a collection of n-tuple xs, multiple folds on a same collection","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"a₁ = foldxl(rf₁, (x[1] for x in xs))\na₂ = foldxl(rf₂, (x[2] for x in xs))\n...\naₙ = foldxl(rfₙ, (x[n] for x in xs))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"can be fused into a single fold using ProductRF","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"a₁, a₂, ..., aₙ = foldxl(ProductRF(rf₁, rf₂, ..., rfₙ), xs)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"provided that the input collection xs and the reducing functions rf₁, rf₂, ..., and rfₙ are not stateful.","category":"page"},{"location":"tutorials/tutorial_missings/#Early-termination","page":"Tutorial: Missing values","title":"Early termination","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Base's maximum reports the maximum to be missing when it receives a container with a missing:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"maximum([1, 2, missing, 3])","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"We can obtain the same behavior by using isless instead of > in findmax_step′:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"function findmax_step′((argmax, max), (index, value))\n argmax, max = isless(max, value) ? (index, value) : (argmax, max)\n return argmax => max\nend\n\nfoldl(findmax_step′, pairs([1, 2, missing, 3]))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"foldl(findmax_step′, ...) does not stop even after it observed missing. We can easily add early termination by using ReduceIf:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 2, missing, 3] |> pairs |> ReduceIf(ismissing ∘ last) |> foldxl(findmax_step′)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Note that ReduceIf(f) is not same as TakeWhile(!f):","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 2, missing, 3] |> pairs |> TakeWhile(!(ismissing ∘ last)) |> foldxl(findmax_step′)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"That is to say, TakeWhile does not evaluate the inner reducing step function with the item that triggers the early termination. That's why we need ReduceIf here.","category":"page"},{"location":"tutorials/tutorial_missings/#findmin-with-missing-and-NaN","page":"Tutorial: Missing values","title":"findmin with missing and NaN","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Unfortunately, we do not have min-compatible \"total\" ordering in Base. Thus, we need to create a function that special-cases missing and NaN:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"function isgreater(x, y)\n xisnan = x != x\n xisnan isa Bool || return false # x is missing\n yisnan = y != y\n yisnan isa Bool || return true # y is missing\n xisnan && return false\n yisnan && return true\n return isless(y, x)\nend\n\n@assert isgreater(2, 1)\n@assert isgreater(1, missing)\n@assert isgreater(NaN, missing)\n@assert isgreater(1, NaN)\n@assert !isgreater(1, 2)\n@assert !isgreater(missing, 1)\n@assert !isgreater(missing, NaN)\n@assert !isgreater(NaN, 1)","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Using isgreater instead of <, we can define findmin_step′ like findmax_step′:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"function findmin_step′((argmin, min), (index, value))\n argmin, min = isgreater(min, value) ? (index, value) : (argmin, min)\n return argmin => min\nend\n\nfoldl(findmax_step′, pairs([1, 2, missing, 3]))","category":"page"},{"location":"tutorials/tutorial_missings/#Extrema-(findminmax)-with-early-termination","page":"Tutorial: Missing values","title":"Extrema (findminmax) with early termination","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"As before, we can fuse findmin_step′ and findmax_step′ using TeeRF. This can also be composed with ReduceIf:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 2, 3, 0, 2] |>\npairs |>\nReduceIf(ismissing ∘ last) |>\nfoldxl(TeeRF(findmin_step′, findmax_step′))","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 2, missing, 0, 2] |>\npairs |>\nReduceIf(ismissing ∘ last) |>\nfoldxl(TeeRF(findmin_step′, findmax_step′))","category":"page"},{"location":"tutorials/tutorial_missings/#Ad-hoc-imputation","page":"Tutorial: Missing values","title":"Ad-hoc imputation","text":"","category":"section"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Using Scan, it is straightforward to fill missing items with the last non-missing item (last observation carried forward):","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 3, missing, 0, 2, missing, missing] |>\npairs |>\nMapSplat(Pair) |>\nScan() do last, (k, v)\n ismissing(v) ? last : k => v\nend |>\ncollect","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"rightif can also be used:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[1, 3, missing, 0, 2, missing, missing] |>\npairs |>\nMapSplat(Pair) |>\nScan(rightif(!(ismissing ∘ right), last)) |>\ncollect\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"Note that the output still may contain missing if the first item is missing:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[missing, 1, missing] |>\npairs |>\nMapSplat(Pair) |>\nScan(rightif(!(ismissing ∘ right), last)) |>\ncollect","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"This can be worked around by specifying init argument for Scan:","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"[missing, 1, missing] |>\npairs |>\nMapSplat(Pair) |>\nScan(rightif(!(ismissing ∘ right), last), 0 => 0) |>\ncollect","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"","category":"page"},{"location":"tutorials/tutorial_missings/","page":"Tutorial: Missing values","title":"Tutorial: Missing values","text":"This page was generated using Literate.jl.","category":"page"},{"location":"explanation/state_machines/#Accumulator-type-transitions-as-state-machines","page":"State machines","title":"Accumulator type transitions as state machines","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"CurrentModule = Transducers","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"Some stateful transducers encode the \"phase\" of reduction as the type of the accumulator (its private state) to achieve efficient composable reductions. This is frequently true especially for parallelizable transducers (i.e., monoid transformations). See the linked docstrings for how each transducer works.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"note: Note\nHere, we use the words accumulator and private state interchangeably. However, note that the state shown in the following diagrams only represent a single component in the \"composite\" accumulator as in acc of __foldl__(rf, acc, xs). For example, for a reducing functionrf = (Consecutive(1, 1) ⨟ ReducePartitionBy(f, rf1))'(rf2)composed of two transducers and one bottom reducing function rf2, the accumulator acc of it has the type transition that is a composition of Consecutive, ReducePartitionBy, and rf2.","category":"page"},{"location":"explanation/state_machines/#Consecutive(N;-step-1)","page":"State machines","title":"Consecutive(N; step = 1)","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"Consecutive with step = 1 first accumulate N-1 elements and then start emitting tuples of size N. The private state of the transducer (in each base case) can be illustrated as follows.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"using FileIO\nusing Kroki\n\ng = graphviz\"\"\"\ndigraph SingleStepConsecutive {\n rankdir = LR;\n node [shape = doublecircle]; \"Buffer{N-1}\";\n node [shape = plain]; \" ... \";\n node [shape = circle];\n \"Buffer{0}\" -> \"Buffer{1}\";\n \"Buffer{1}\" -> \" ... \";\n \" ... \" -> \"Buffer{N-2}\";\n \"Buffer{N-2}\" -> \"Buffer{N-1}\";\n \"Buffer{N-1}\" -> \"Buffer{N-1}\" [label = \"NTuple{N,Any}\"];\n}\n\"\"\"\nsave(\"SingleStepConsecutive.svg\", g)\nnothing","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"(Image: )","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"For Consecutive(N; step = 1) transducer, the types of the private state are Buffer{0} (initial value), Buffer{1}, Buffer{2}, ..., Buffer{N-2}, and Buffer{N-1}, defined as:","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"Left{K} = NTuple{K,Any}\nRight{K} = NTuple{K,Any}\nBuffer{K} = Tuple{Left{K}, Right{K}} # K = 0, 1, ..., N-1","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The Right{K} component of Buffer tuple keeps the most recent K elements this transducer received. Once the state reaches to the type Buffer{N-1}, this transducer start emitting an N-tuple for each iteration (as indicated in the edge label NTuple{N,Any}). The loop with the accumulator of type Buffer{N-1} is the major component of the loop (i.e., it is used O(mathrmlength(xs)) times when reducing an input collection mathrmxs). The \"main loop\" accumulators such as Buffer{N-1} are marked by the double circles. The accumulator types used only for O(1) times are marked by the single circles and called prelude (ref is_prelude). See tail-call \"function-barrier\" pattern for how this information is used to generate efficient reductions.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The Left{K} component of Buffer tuple keeps the first K elements observed in this base case; this is used only in the parallel reduction, for combining to the base case left to this base case.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The private state of Consecutive with step > 1 additionally contains the counter. It does not contain Left since it cannot be used for parallel reductions.","category":"page"},{"location":"explanation/state_machines/#WordsXF()","page":"State machines","title":"WordsXF()","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"Parallel word count tutorial explains how to build a transducer WordsXF that can be used to split words in parallel, in a composable manner. The following diagram shows the transition of its accumulator type. It emits String only after it reaches Vacant, if a word followed by a space is observed (hence Union). See also the definition of extract(::Vacant, ::Vacant) in the tutorial.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"using FileIO\nusing Kroki\n\ng = graphviz\"\"\"\ndigraph WordsXF {\n rankdir = LR;\n node [shape = doublecircle]; \"Vacant\";\n node [shape = circle];\n \"Chunk\" -> \"Chunk\" [label = \"Nothing\"];\n \"Chunk\" -> \"Vacant\" [label = \"Nothing\"];\n \"Vacant\" -> \"Vacant\" [label = \"Union{Nothing,String}\"];\n}\n\"\"\"\nsave(\"WordsXF.svg\", g)\nnothing","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"(Image: )","category":"page"},{"location":"explanation/state_machines/#ReducePartitionBy(f,-rf,-[init])","page":"State machines","title":"ReducePartitionBy(f, rf, [init])","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The private state of ReducePartitionBy starts as an Unseen() and then transition to Chunk at the first iteration. It then stays as a Chunk until the result of f(x) for input element x changes for the first time; at this point the state stays as a Vacant that holds the accumulators of rf for the first (left most) chunk and the current chunk. When the value of f(x) is changed for the second time or later, the accumulator of rf is completeed and emitted to the inner reducing function. This is denoted as by the edge label R? in the diagram. The question mark ? is for indicating that the result of type R is not emitted for every iteration; it's only when f(x) is changed.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"using FileIO\nusing Kroki\n\ng = graphviz\"\"\"\ndigraph ReducePartitionBy {\n rankdir = LR;\n node [shape = doublecircle]; Vacant;\n node [shape = circle];\n Unseen -> Chunk;\n Chunk -> Chunk;\n Chunk -> Vacant;\n Vacant -> Vacant [label = \"R?\"];\n}\n\"\"\"\nsave(\"ReducePartitionBy.svg\", g)\nnothing","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"(Image: )","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The Vacant state keeps the first (pre-complete) accumulator of rf so that it can be combineed to the base case left to the current base case.","category":"page"},{"location":"explanation/state_machines/#ReduceSplitBy(f,-rf,-init)","page":"State machines","title":"ReduceSplitBy(f, rf, init)","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"The private state of ReduceSplitBy starts as a PreChunk and stays as a Chunk until f(x) is true for the input element x. It may jump directly into PreVacant if f(x) is true for the first input element x. From PreVacant, the state is changed to Vacant unless f(x) is true. Each time f(x) is evaluated to true, the accumulator of rf is completeed and its result (of type R) is emitted.","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"using FileIO\nusing Kroki\n\ng = graphviz\"\"\"\ndigraph ReduceSplitBy {\n rankdir = LR;\n node [shape = doublecircle]; PreVacant Vacant;\n node [shape = circle];\n PreChunk -> Chunk;\n PreChunk -> PreVacant;\n Chunk -> Chunk;\n Chunk -> PreVacant;\n PreVacant:se -> Vacant:sw;\n Vacant -> Vacant;\n Vacant -> PreVacant [label = \"R\"];\n PreVacant -> PreVacant [label = \"R\"];\n}\n\"\"\"\nsave(\"ReduceSplitBy.svg\", g)\nnothing","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"(Image: )","category":"page"},{"location":"explanation/state_machines/#tail-call-function-barrier","page":"State machines","title":"Tail-call \"function-barrier\" pattern","text":"","category":"section"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"To improve the type stability of the \"main loop\" (the transition between the double circles), it is often beneficial to unroll the initial transitions (the single circles). Schematically, we compose code like below:","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"# Given:\nrf # reducing function\nacc # accumulator\niter # input collection\nistate # iterator state\n\n@assert is_prelude(acc)\nT1 = typeof(acc)\nwhile true\n y = iterate(iter, istate)\n y === nothing && return acc\n (x, istate) = y\n acc = rf(acc, x)\n acc isa T1 || break\nend\n\n@assert is_prelude(acc)\nT2 = typeof(acc)\nwhile true\n y = iterate(iter, istate)\n y === nothing && return acc\n (x, istate) = y\n acc = rf(acc, x)\n acc isa T2 || break\nend\n\n# ... and so on ...\n\n@assert is_prelude(acc)\nTN = typeof(acc)\nwhile true\n y = iterate(iter, istate)\n y === nothing && return acc\n (x, istate) = y\n acc = rf(acc, x)\n acc isa TN || break\nend\n\n# Now suppose we are out of the \"prelude chain\":\n@assert !is_prelude(acc)\n\n# ...then loop like usual:\nwhile true\n y = iterate(iter, istate)\n y === nothing && return acc\n (x, istate) = y\n acc = rf(acc, x)\nend","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"Note that this code snippet is only for explaining the concept. For example, it is not possible to know how many while loops to generate a priori. It also assumes that the transition of the prelude accumulator which is not the case (see, e.g., ReduceSplitBy). Instead, several __foldl__ methods implement this strategy using what we call tail-call function-barrier pattern (ref: an example).","category":"page"},{"location":"explanation/state_machines/","page":"State machines","title":"State machines","text":"For a previous discussion on this strategy, see also: Tail-call optimization and function-barrier -based accumulation in loops - Internals & Design - JuliaLang.","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"EditURL = \"../../../examples/empty_result_handling.jl\"","category":"page"},{"location":"howto/empty_result_handling/#Empty-result-handling","page":"Empty result handling","title":"Empty result handling","text":"","category":"section"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Transducible processes such as foldl try to do the right thing even when init is not given, if the given binary operation step is supported by InitialValues.jl (for example, +, *, &, and | are supported). However, those functions throw an exception if the given collection is empty or filtered out by the transducers:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"using Transducers\n\nadd1(x) = x + 1\n\nerr = try # hide\nfoldl(*, Map(add1), [])\ncatch _err; _err; end # hide\nprint(stdout, \"ERROR: \") # hide\nshowerror(stdout, err) # hide","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"To write robust code, it is recommended to use init if there is a reasonable default. However, it may be useful to postpone \"materializing\" the result. In such case, Init can be used as a placeholder.","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"result = foldl(*, Map(add1), [], init=Init)\nnothing # hide","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"init=Init is a short-hand notation of init=Init(*) (so that * does not have to be repeated):","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"@assert result === foldl(*, Map(add1), [], init=Init(*))","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Note also that transduce can be used for passing init as a positional argument:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"@assert result === transduce(Map(add1), Completing(*), Init, [])","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Since the input collection [] is empty, result is Init(*) (which is an InitialValues.InitialValue):","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"using InitialValues: InitialValue\n@assert result::InitialValue === Init(*)","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Init(*) is the left identity of *. Multiplying it with any x from right returns x as-is. This property may be useful, e.g., if result is known to be a scalar that is multiplied by a matrix just after the foldl:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"result * ones(2, 2)","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"The identities Init(*) and Init(+) can be converted to numbers:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"convert(Int, Init(*))","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Init(*) can also be converted to a String:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"convert(String, Init(*))","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"This means that no special code is required if the result is going to be stored into, e.g., an Array or a struct:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"xs = [true, true]\nxs[1] = Init(+)\nxs","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"They can be converted into numbers also by using Integer:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"Integer(Init(+))","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"or float:","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"float(Init(*))","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"","category":"page"},{"location":"howto/empty_result_handling/","page":"Empty result handling","title":"Empty result handling","text":"This page was generated using Literate.jl.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"EditURL = \"../../../examples/tutorial_parallel.jl\"","category":"page"},{"location":"tutorials/tutorial_parallel/#tutorial-parallel","page":"Tutorial: Parallelism","title":"Parallel processing tutorial","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"See also: Overview of parallel processing in Transducers.jl","category":"page"},{"location":"tutorials/tutorial_parallel/#Quick-examples","page":"Tutorial: Parallelism","title":"Quick examples","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/#Sequential-processing","page":"Tutorial: Parallelism","title":"Sequential processing","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using Transducers\n\nxs = randn(10_000_000)\nfoldl(+, Map(sin), xs)","category":"page"},{"location":"tutorials/tutorial_parallel/#Thread-based-parallelism","page":"Tutorial: Parallelism","title":"Thread-based parallelism","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Just replace foldl with foldxt, to make use of multiple cores:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(+, Map(sin), xs)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"(In my laptop (4 core machine) I start seeing some speedup around length(xs) ≥ 100_000 for this transducer and reducing function.)","category":"page"},{"location":"tutorials/tutorial_parallel/#Process-based-parallelism","page":"Tutorial: Parallelism","title":"Process-based parallelism","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using Distributed\n#addprocs(4) # add worker processes\n\nfoldxd(+, Map(sin), xs)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"(Note: there is likely no speedup for light-weight computation and large input data like this, when using foldxd.)","category":"page"},{"location":"tutorials/tutorial_parallel/#Parallel-processing-with-iterator-comprehensions","page":"Tutorial: Parallelism","title":"Parallel processing with iterator comprehensions","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"You can also use parallel processing functions in Transducers.jl such as foldxt, foldxd, tcollect, dcollect, tcopy and dcopy with iterator comprehensions:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(+, (sin(x) for x in xs if abs(x) < 1); basesize = 500_000)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(+, (x * y for x in 1:3, y in 1:3))","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"tcollect(sin(x) for x in xs if abs(x) < 1)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using StructArrays: StructVector\ntable = StructVector(a = [1, 2, 3], b = [5, 6, 7])\n\ntcopy((A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a))","category":"page"},{"location":"tutorials/tutorial_parallel/#When-can-I-use-foldxt-and-foldxd?","page":"Tutorial: Parallelism","title":"When can I use foldxt and foldxd?","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/#Requirement-1:-Associative-reducing-step-function","page":"Tutorial: Parallelism","title":"Requirement 1: Associative reducing step function","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Parallel reductions such as foldxt and foldxd requires associative reducing step function. Recall that associativity means that the grouping of evaluations of binary operator does not matter:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"op = + # for example\na, b, c = 1, 2, 3 # for example\n\n@assert op(op(a, b), c) == op(a, op(b, c))","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Given this property, computations like a + b + c + d can be done with different \"groupings\":","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":" a + b + c + d\n\n= ((a + b) + c) + d +\n / \\\n + d\n / \\\n + c foldl-like grouping\n / \\\n a b\n\n= (a + b) + (c + d) +\n / \\\n / \\\n / \\ reduce-like grouping\n + +\n / \\ / \\\n a b c d","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Notice that, in the last grouping, computation of c + d does not have to wait for the result of a + b. This is why we need associativity for parallel execution.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"note: Note\nDo not confuse associativity with commutativity op(a, b) = op(b, a). For example, matrix multiplication *(::Matrix, ::Matrix) is associative but not commutative in general. However, since foldxt only requires associativity, it is valid to use foldxt(*, xf, matrices).","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"As reducing function + is associative, it can be used with foldxt (and foldxd):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"y1 = begin # hide\nfoldxt(+, Map(identity), 1:10; init = 0, basesize = 1)\nend # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"and the result is the same as the sequential version:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"y2 = begin # hide\nfoldl(+, Map(identity), 1:10; init = 0)\nend # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Note: basesize is for forcing foldxt to avoid falling back to foldl for small length container such as 1:10.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"On the other hand, binary function - is not associative. Thus, foldxt cannot be used instead of foldl (they produce different result):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"y3 = begin # hide\nfoldxt(-, Map(identity), 1:10; init = 0, basesize = 1)\nend # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"y4 = begin # hide\nfoldl(+, Map(identity), 1:10; init = 0)\nend # hide","category":"page"},{"location":"tutorials/tutorial_parallel/#Requirement-2:-stateless-transducers","page":"Tutorial: Parallelism","title":"Requirement 2: stateless transducers","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Parallel reduction only work with stateless transducers Map, Filter, Cat, etc. and you will get an error when using stateful transducers such as Scan with foldxt or foldxd:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"err = try # hide\nfoldxt(+, Scan(+), 1:10; basesize = 1)\ncatch _err; _err; end # hide\nprint(stdout, \"ERROR: \") # hide\nshowerror(stdout, err) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Stateful transducers cannot be used with foldxt because it is impossible to start processing input collection from the middle when the transducers need to know all previous elements (= stateful).","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"ScanEmit is a stateful transducer but it is assumed that it is used in a context that outputs can be treated as stateless (see: Splitting a string into words and counting them in parallel).","category":"page"},{"location":"tutorials/tutorial_parallel/#tutorial-parallel-collect","page":"Tutorial: Parallelism","title":"Example: parallel collect","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"note: Note\nThis section explains the implementation ideas of parallel collect. Pre-defined functions such as tcopy and dcopy should cover many use-cases.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Suppose (pretend) there is a compute-heavy transducer:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"xf_compute = opcompose(Filter(!ismissing), Map(x -> x^2))\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Transducers.jl supports applying this to an input container and then collecting the results into another container. It can be done sequentially (collect, copy, etc.) and in parallel using threads (tcollect, tcopy) or using multiple processes (dcollect, dcopy). For example:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"xs = [abs(x) > 1 ? missing : x for x in randn(10_000)]\ny1 = collect(xf_compute, xs)\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Doing this in parallel is as easy as using tcollect or dcollect. However, it is easy to do this manually, too:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using BangBang: append!!\n\nsingleton_vector(x) = [x]\ny2 = foldxt(append!!, xs |> xf_compute |> Map(singleton_vector))\n@assert y1 == y2","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This code illustrates the common pattern in parallel processing:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Put a result from the transducer in a \"singleton solution\". Here, it is [x].\nThen \"merge\" the (singleton) solution into the existing one. This is done by append!! in the above example.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"To illustrate how foldxt(append!!, xs |> ... |> Map(singleton_vector)) works, let's create a reducing function that records the arguments and returned values of append!!:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"chan = Channel(Inf)\n\nfunction append_and_log!!(a, b)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"As arguments and output may be mutated later, we use copy to record the snapshots of their values at this moment:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":" a0 = copy(a)\n b0 = copy(b)\n c = append!!(a, b)\n put!(chan, (a0, b0) => copy(c))\n return c\nend\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This function can be used instead of append!!. Let's try simpler and shorter example. This is equivalent to collect(1:4):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(append_and_log!!, Map(singleton_vector), 1:4; basesize = 1, init = Union{}[])","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"(See below for why we are using init = Union{}[] here.)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Here is the list of arguments and returned value of append!! in this reduction:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"records = Pair[]\nwhile isready(chan)\n push!(records, take!(chan))\nend\nrecords","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This recorded inputs and outputs of append!! show that its \"call tree\" is:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":" [1,2,3,4] <------------- append!!([1,2], [3,4]) == [1,2,3,4]\n / \\\n [1,2] [3,4] <------- append!!([3], [4]) == [3, 4]\n / \\ / \\\n [1] [2] [3] [4] <---- append!!([], [4]) == [4]\n / \\ / \\ / \\ / \\\n[] [1] [] [2] [] [3] [] [4]","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Compare this to the example a + b + c + d above.","category":"page"},{"location":"tutorials/tutorial_parallel/#Optimization-and-generic-container-handling","page":"Tutorial: Parallelism","title":"Optimization and generic container handling","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Above usage of foldxt is not quite efficient as singleton_vector allocates small objects in the heap. Thus, it makes sense to use immutable objects for the singleton solutions so that Julia compiler can eliminate allocation of the intermediate singleton solutions. Here, this can be done by simply using SVectorinstead of singleton_vector:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using StaticArrays: SVector\n\nfoldxt(append!!, Map(SVector), 1:4)","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"However, notice that the return value is a static vector. This is not ideal when the input collection is large. The output collection type can be specified by init. We can simply use init = Union{}[] in this case:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(append!!, Map(SVector), 1:4; init = Union{}[])","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Note that passing Vector to init of foldxt is usually a wrong choice as it would mean that the same object is simultaneously mutated by different threads. However, since Vector{Union{}} cannot have any element (as there is no object of type Union{}), using Union{}[] for init is an exception and it is a good way to indicate that output vector should use the \"smallest\" eltype required. That is to say, append!! widens the vector \"just enough\" to fit the resulting elements.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"For generic containers (e.g., various table types), use BangBang.Empty as the empty initial value. This is useful for creating a table object such as DataFrame as the result of parallel processing:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using BangBang: Empty\nusing DataFrames: DataFrame\n\nans = begin # hide\nfoldxt(append!!, Map(x -> SVector((a = x,))), 1:4; init = Empty(DataFrame))\nend # hide\nText(ans) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"It is slightly more tricky to make this approach work with other table types such as StructArrays and TypedTables. Use tcopy or dcopy to work with generic containers.","category":"page"},{"location":"tutorials/tutorial_parallel/#Example:-ad-hoc-histogram","page":"Tutorial: Parallelism","title":"Example: ad-hoc histogram","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Following example counts number of occurrence of each leading digit in a distribution of random numbers. First, let's create \"singleton solutions\" using transducers:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"xs = 1_000_000 * randn(10_000_000)\ndicts1 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x\n y = digits(floor(Int, x))[end]\n Dict(y => 1)\nend\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"The singleton solutions can be merged using mergewith!(+, a, b). Conveniently, mergewith!(+) is the curried form (args...) -> mergewith!(+, args...):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"rf! = mergewith!(+)\nrf!(Dict(:a => 1, :b => 2), Dict(:b => 3, :c => 4))","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This is the form of binary function appropriate for foldl and foldxt.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Note that it is OK to use in-place function mergewith! here because the dictionary passed as a is created by Dict(y => 1) and not shared by anyone. When there is no such guarantee, passing init = OnInit(Dict{Int,Int}) is a good option. Note that passing init = Dict{Int,Int}() to foldxt is not correct as multiple tasks would share and try to mutate the same dictionary this way.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Let's try this with parallel foldxt:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"counts1 = foldxt(mergewith!(+), dicts1)\nnothing # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Compare the result with foldl:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"counts2 = foldl(mergewith!(+), dicts1)\n@assert counts1 == counts2","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Hopefully the result is close to the Benford's law - Wikipedia:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"let n = sum(values(counts1))\n sort!(keys(counts1) .=> values(counts1) ./ n)\nend","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Since we are counting only nine elements, it is actually better to use fixed-size container such as a tuple in this case:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"dicts2 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x\n y = digits(floor(Int, x))[end]\n ntuple(i -> i == y, 9)\nend\n\ncounts3 = foldxt(dicts2; init=ntuple(_ -> 0, 9)) do a, b\n map(+, a, b)\nend\n@assert Dict(zip(1:9, counts3)) == counts1","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Note that, as tuples are immutable, it is valid to pass it as init of foldxt.","category":"page"},{"location":"tutorials/tutorial_parallel/#MicroCollections.jl-for-efficient-singleton-solution","page":"Tutorial: Parallelism","title":"MicroCollections.jl for efficient singleton solution","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"When the appropriate \"bins\" are not known, mergewith!(+)-based strategy is more appropriate. However, it is not ideal to allocate a small container like Dict(y => 1) in the heap for each iteration. MicroCollections.jl provides singleton (and empty) containers that are designed for this usecase. The SingletonDict is \"upcast\" to the mutable Dict in the first invocation when merged with BangBang.jl functions:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"using BangBang: mergewith!!\nusing MicroCollections: SingletonDict\n\nacc1 = mergewith!!(+, SingletonDict(:a => 1), SingletonDict(:b => 1))\nText(acc1) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This dictionary is reused in the subsequent iterations:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"acc2 = mergewith!!(+, acc1, SingletonDict(:b => 1))\nText(acc2) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"acc3 = mergewith!!(+, acc2, SingletonDict(:c => 1))\nText(acc3) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"The first result is reused across these iterations (within a single thread).","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"@assert acc1 === acc2 === acc3","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Finally, Dicts from different threads are merged using the same function mergewith!!(+):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"acc4 = Dict(:a => 5, :c => 3) # from different thread\nacc5 = mergewith!!(+, acc3, acc4)\nText(acc5) # hide","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Thus, dicts1 can be optimized simply by replacing Dict(y => 1) with SingletonDict(y => 1):","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"dicts3 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x\n y = digits(floor(Int, x))[end]\n SingletonDict(y => 1)\nend\n\ncounts4 = foldxt(mergewith!!(+), dicts3)\n@assert counts1 == counts4","category":"page"},{"location":"tutorials/tutorial_parallel/#Example:-early-termination","page":"Tutorial: Parallelism","title":"Example: early termination","text":"","category":"section"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"Find the first element that is multiple of three:","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"foldxt(ReduceIf(x -> x % 3 == 0), 1:10; init = nothing, basesize = 1) do _, x\n # # Uncomment for demo:\n # x == 3 ? sleep(0.1) : @show x # give other tasks a chance to finish first\n return x\nend","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This snippet always returns 3, even though the reductions for c = 6 and c = 9 may finish first.","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"","category":"page"},{"location":"tutorials/tutorial_parallel/","page":"Tutorial: Parallelism","title":"Tutorial: Parallelism","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/manual/#Transducers-and-Transducible-processes","page":"Manual","title":"Transducers and Transducible processes","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Pages = [\"manual.md\"]\nOrder = [:function, :type]","category":"page"},{"location":"reference/manual/#Transducible-processes","page":"Manual","title":"Transducible processes","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"foldxl\ntransduce\nfoldl\nforeach\nfoldxt\nfoldxd\ndtransduce\neduction\nmap!\ncopy!\ncopy\ntcopy\ndcopy\nappend!\nTransducers.append!!\ncollect\ntcollect\ndcollect\nChannel","category":"page"},{"location":"reference/manual/#Transducers.foldxl","page":"Manual","title":"Transducers.foldxl","text":"foldxl(step, xf::Transducer, reducible; init, simd) :: T\nfoldxl(step, reducible; init, simd) :: T\nfoldl(step, xf::Transducer, reducible; init, simd) :: T\nfoldl(step, ed::Eduction; init, simd) :: T\ntransduce(xf, step, init, reducible, [executor]; simd) :: Union{T, Reduced{T}}\n\neXtended left fold. Compose transducer xf with reducing step function step and reduce itr using it.\n\nnote: Note\ntransduce differs from foldxl as Reduced{T} is returned if the transducer xf or step aborts the reduction and step is not automatically wrapped by Completing.\n\nThis API is modeled after transduce in Clojure.\n\nFor parallel versions, see foldxt and foldxd.\n\nSee also: Empty result handling.\n\nArguments\n\nxf::Transducer: A transducer.\nstep: A callable which accepts 1 and 2 arguments. If it only accepts 2 arguments, wrap it with Completing to \"add\" 1-argument form (i.e., complete protocol).\nreducible: A reducible object (array, dictionary, any iterator, etc.).\nexecutor: Specify an executor. See SequentialEx.\ninit: An initial value fed to the first argument to reducing step function step. This argument can be omitted for well know binary operations like + or *. Supported binary operations are listed in InitialValues.jl documentation. When Init (not the result of Init, such as Init(*)) is given, it is automatically \"instantiated\" as Init(step) (where step is appropriately unwrapped if step is a Completing). See Empty result handling in the manual for more information.\nsimd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(Filter(isodd), 1:4, init=0.0) do state, input\n @show state, input\n state + input\n end\n(state, input) = (0.0, 1)\n(state, input) = (1.0, 3)\n4.0\n\njulia> foldxl(+, 1:5 |> Filter(isodd))\n9\n\njulia> 1:5 |> Filter(isodd) |> foldxl(+)\n9\n\nSince TeeRF requires the extended fold protocol, foldl(TeeRF(min, max), [5, 2, 6, 8, 3]) does not work while it works with foldxl:\n\njulia> foldxl(TeeRF(min, max), [5, 2, 6, 8, 3])\n(2, 8)\n\nThe unary method of foldlx is useful when combined with |>:\n\njulia> (1:5, 4:-1:1) |> Cat() |> Filter(isodd) |> Enumerate() |> foldxl() do a, b\n a[2] < b[2] ? b : a\n end\n(3, 5)\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.transduce","page":"Manual","title":"Transducers.transduce","text":"transduce(xf, step, init, reducible) :: Union{T, Reduced{T}}\n\nSee foldxl.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.foldl","page":"Manual","title":"Base.foldl","text":"foldl(step, xf::Transducer, reducible; init, simd) :: T\nfoldl(step, ed::Eduction; init, simd) :: T\n\nSee foldxl.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.foreach","page":"Manual","title":"Base.foreach","text":"foreach(eff, xf::Transducer, reducible; simd)\nforeach(eff, ed::Eduction; simd)\n\nFeed the results of xf processing items in reducible into a unary function eff. This is useful when the primary computation at the bottom is the side-effect. It is also equivalent to foreach(eff, eduction(xf, coll)). Note that\n\nforeach(eduction(xf, coll)) do x\n ...\nend\n\ncan be more efficient than\n\nfor x in eduction(xf, coll)\n ...\nend\n\nas the former does not have to translate the transducer protocol to the iterator protocol.\n\nforeach supports all constructs in the native for loop as well as the enhancements [julia_issue_22891] to break with a value (break D(x) below) and append the else clause (E(x) below).\n\n[julia_issue_22891]: See also: break with value + loop else clauses (JuliaLang/julia#22891)\n\nThis native for loop\n\nans = for x in xs\n A(x)\n B(x) && break\n C(x) && break D(x)\nelse\n E(x)\nend\n\ncan be written as\n\nans = foreach(Map(identity), xs) do x\n A(x)\n B(x) && return reduced()\n C(x) && return reduced(D(x))\n x # required for passing `x` to `E(x)` below\nend |> ifunreduced() do x\n E(x)\nend\n\nSee: mapfoldl, reduced, ifunreduced.\n\ncompat: Transducers.jl 0.3\nforeach is changed to return what the do block (eff function) returns as-is in version 0.3. This was required for supporting \"for-else\" (|> ifunreduced). Previously, it only supported break-with-value and always applied unreduced before it returns.\n\nExamples\n\njulia> using Transducers\n\njulia> foreach(eduction(Filter(isodd), 1:4)) do input\n @show input\n end\ninput = 1\ninput = 3\n3\n\njulia> foreach(Filter(!ismissing), [1, missing, 2, 3]) do input\n @show input\n if iseven(input)\n return reduced()\n end\n end\ninput = 1\ninput = 2\nReduced(nothing)\n\nIt is often useful to append |> unreduced to unwrap Reduced in the final result (note that |> here is the standard function application, not the transducer composition).\n\njulia> foreach(Filter(!ismissing), [1, missing, 2, 3]) do input\n reduced(\"got $input\")\n end |> unreduced\n\"got 1\"\n\nCombination of break-with-value and for-else is useful for triggering action after (e.g.) some kind of membership testing failed:\n\njulia> has2(xs) = foreach(Filter(!ismissing), xs) do input\n input == 2 && reduced(true)\n end |> ifunreduced() do input\n @show input\n false\n end;\n\njulia> has2([1, missing, 2, 3])\ntrue\n\njulia> has2([1, missing])\ninput = false\nfalse\n\nHowever, note the output input = false in the last example. This is because how && works in Julia\n\njulia> false && \"otherwise\"\nfalse\n\nThus, pure membership testing functions like has2 above can be written in a more concise manner:\n\njulia> simpler_has2(xs) = foreach(Filter(!ismissing), xs) do input\n input == 2 && reduced(true)\n end |> unreduced;\n\njulia> simpler_has2([1, missing, 2, 3])\ntrue\n\njulia> simpler_has2([1, missing])\nfalse\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.foldxt","page":"Manual","title":"Transducers.foldxt","text":"foldxt(step, xf, reducible; [init, simd, basesize, stoppable, nestlevel]) :: T\n\neXtended threaded fold (reduce). This is a multi-threaded reduce based on extended fold protocol defined in Transducers.jl.\n\nThe \"bottom\" reduction function step(::T, ::T) :: T must be associative and init must be its identity element.\n\nTransducers composing xf must be stateless (e.g., Map, Filter, Cat, etc.) except for ScanEmit. Note that Scan is not supported (although possible in theory). Early termination requires Julia ≥ 1.3.\n\nUse tcollect or tcopy to collect results into a container.\n\nSee also: Parallel processing tutorial, foldxl, foldxd.\n\nKeyword Arguments\n\nbasesize::Integer = amount(reducible) ÷ nthreads(): A size of chunk in reducible that is processed by each worker. A smaller size may be required when:\ncomputation time for processing each item fluctuates a lot\ncomputation can be terminated by reduced or transducers using it, such as ReduceIf\nstoppable::Bool: [This option usually does not have to be set manually.] The threaded fold executed in the \"stoppable\" mode used for optimizing reduction with reduced has a slight overhead if reduced is not used. This mode can be disabled by passing stoppable = false. It is usually automatically detected and set appropriately. Note that this option is purely for optimization and does not affect the result value.\nnestlevel::Union{Integer,Val}: Specify how many inner Cat (flatten) transducers to be multi-threaded (using TCat). It must be a positive integer, Val of positive integer, or Val(:inf). Val(:inf) means to use multi-threading for all Cat transducers. Note that Cat transducer should be statically known. That is to say, the fold implementation sees two Cats in ... |> Map(f) |> Cat() |> Cat() but only one Cat in ... |> Map(x -> f(x) |> Cat()) |> Cat() even though they are semantically identical.\nFor other keyword arguments, see foldl.\n\ncompat: Transducers.jl 0.4.23\nKeyword option stoppable requires at least Transducers.jl 0.4.23.\n\nExamples\n\njulia> using Transducers\n\njulia> foldxt(+, 1:3 |> Map(exp) |> Map(log))\n6.0\n\njulia> using BangBang: append!!\n\njulia> foldxt(append!!, Map(x -> 1:x), 1:2; basesize=1, init=Union{}[])\n3-element Vector{Int64}:\n 1\n 1\n 2\n\njulia> 1:5 |> Filter(isodd) |> foldxt(+)\n9\n\njulia> foldxt(TeeRF(min, max), [5, 2, 6, 8, 3])\n(2, 8)\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.foldxd","page":"Manual","title":"Transducers.foldxd","text":"foldxd(step, xform::Transducer, array; [init, simd, basesize, threads_basesize, pool])\n\neXtended distributed fold (reduce). This is a distributed reduce based on extended fold protocol defined in Transducers.jl.\n\nUnlike foldxt, early termination by reduced is not supported yet.\n\nUse dcollect or dcopy to collect results into a container.\n\nSee also: Parallel processing tutorial, foldxl, foldxt.\n\ncompat: Transducers.jl 0.4.3\nNew in version 0.4.3.\n\nKeyword Arguments\n\npool::AbstractWorkerPool: Passed to Distributed.remotecall.\nbasesize::Integer = amount(array) ÷ nworkers(): A size of chunk in array that is processed by each worker. A smaller size may be required when computation time for processing each item can fluctuate a lot.\nthreads_basesize::Integer = basesize ÷ nthreads(): A size of chunk in array that is processed by each task in each worker process. The default setting assumes that the number of threads used in all workers are the same. For heterogeneous setup where each worker process has different number of threads, it may be required to use smaller threads_basesize and basesize to get a good performance.\nFor other keyword arguments, see foldl.\n\nExamples\n\njulia> using Transducers\n\njulia> foldxd(+, 1:3 |> Map(exp) |> Map(log))\n6.0\n\njulia> 1:5 |> Filter(isodd) |> foldxd(+)\n9\n\njulia> foldxd(TeeRF(min, max), [5, 2, 6, 8, 3])\n(2, 8)\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.dtransduce","page":"Manual","title":"Transducers.dtransduce","text":"dtransduce(xform::Transducer, step, init, array; [simd, basesize, threads_basesize, pool])\n\nSee foldxd and transduce.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.eduction","page":"Manual","title":"Transducers.eduction","text":"eduction(xf::Transducer, coll)\nxf(coll)\ncoll |> xf\n\nCreate a iterable and reducible object.\n\nIterable.\nReducible; i.e., it can be handled by transduce efficiently.\n\nThis API is modeled after eduction in Clojure.\n\nnote: Note\nEven though eduction returns an iterable, it is highly recommended to use the foldl-based method provided by Transducers.jl when the performance is important.\n\nExamples\n\njulia> using Transducers\n\njulia> for x in 1:1000 |> Filter(isodd) |> Take(3) # slow\n @show x\n end\nx = 1\nx = 3\nx = 5\n\njulia> foreach(1:1000 |> Filter(isodd) |> Take(3)) do x # better\n @show x\n end;\nx = 1\nx = 3\nx = 5\n\n\n\n\n\neduction(iterator::Iterators.Generator)\neduction(iterator::Iterators.Filter)\neduction(iterator::Iterators.Flatten)\n\nConvert an iterator to an eduction. The iterators that are typically used in the generator comprehensions are supported.\n\ncompat: Transducers.jl 0.3\nNew in version 0.3.\n\nExamples\n\njulia> using Transducers\n\njulia> iter = (y for x in 1:10 if x % 2 == 0 for y in (x, x + 1));\n\njulia> ed = eduction(iter);\n\njulia> collect(iter) == collect(ed)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.map!","page":"Manual","title":"Base.map!","text":"map!(xf::Transducer, dest, src; simd)\n\nFeed src to transducer xf, storing the result in dest. Collections dest and src must have the same shape. Transducer xf may contain filtering transducers. If some entries src are skipped, the corresponding entries in dest will be unchanged. Transducer xf must not contain any expansive transducers such as MapCat.\n\nSee also copy!.\n\nExamples\n\njulia> using Transducers\n\njulia> xs = collect(1:5)\n ys = zero(xs)\n map!(Filter(isodd), ys, xs)\n5-element Vector{Int64}:\n 1\n 0\n 3\n 0\n 5\n\njulia> ans === ys\ntrue\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.copy!","page":"Manual","title":"Base.copy!","text":"copy!(xf::Transducer, dest, src)\n\nFeed src to transducer xf, storing the result in dest. Collections dest and src may have the same shape. Source src must be iterable. Destination dest must implement empty! and push!.\n\nSee also map!.\n\nExamples\n\njulia> using Transducers\n\njulia> copy!(opcompose(PartitionBy(x -> x ÷ 3), Map(sum)), Int[], 1:10)\n4-element Vector{Int64}:\n 3\n 12\n 21\n 19\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.copy","page":"Manual","title":"Base.copy","text":"copy(xf::Transducer, T, foldable) :: Union{T, Empty{T}}\ncopy(xf::Transducer, foldable::T) :: Union{T, Empty{T}}\ncopy([T,] eduction::Eduction) :: Union{T, Empty{T}}\n\nProcess foldable with a transducer xf and then create a container of type T filled with the result. Return BangBang.Empty{T} if the transducer does not produce anything. (This is because there is no consistent interface to create an empty container given its type and not all containers support creating an empty container.)\n\nFor parallel versions, see tcopy and dcopy.\n\ncompat: Transducers.jl 0.4.4\nNew in version 0.4.4.\n\ncompat: Transducers.jl 0.4.8\ncopy now accepts eductions.\n\nExamples\n\njulia> using Transducers\n using BangBang: Empty\n\njulia> copy(Map(x -> x => x^2), Dict, 2:2)\nDict{Int64, Int64} with 1 entry:\n 2 => 4\n\njulia> @assert copy(Filter(_ -> false), Set, 1:1) === Empty(Set)\n\njulia> using TypedTables\n\njulia> @assert copy(Map(x -> (a=x, b=x^2)), Table, 1:1) == Table(a=[1], b=[1])\n\njulia> using StructArrays\n\njulia> @assert copy(Map(x -> (a=x, b=x^2)), StructVector, 1:1) == StructVector(a=[1], b=[1])\n\njulia> using DataFrames\n\njulia> @assert copy(\n Map(x -> (A = x.a + 1, B = x.b + 1)),\n DataFrame(a = [1], b = [2]),\n ) == DataFrame(A = [2], B = [3])\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.tcopy","page":"Manual","title":"Transducers.tcopy","text":"tcopy(xf::Transducer, T, reducible; basesize) :: Union{T, Empty{T}}\ntcopy(xf::Transducer, reducible::T; basesize) :: Union{T, Empty{T}}\ntcopy([T,] itr; basesize) :: Union{T, Empty{T}}\n\nThread-based parallel version of copy. Keyword arguments are passed to foldxt.\n\nSee also: Parallel processing tutorial (especially Example: parallel collect).\n\ncompat: Transducers.jl 0.4.5\nNew in version 0.4.5.\n\ncompat: Transducers.jl 0.4.8\ntcopy now accepts iterator comprehensions and eductions.\n\nExamples\n\njulia> using Transducers\n\njulia> tcopy(Map(x -> x => x^2), Dict, 2:2)\nDict{Int64, Int64} with 1 entry:\n 2 => 4\n\njulia> using TypedTables\n\njulia> @assert tcopy(Map(x -> (a=x,)), Table, 1:1) == Table(a=[1])\n\njulia> using StructArrays\n\njulia> @assert tcopy(Map(x -> (a=x,)), StructVector, 1:1) == StructVector(a=[1])\n\ntcopy works with iterator comprehensions and eductions (unlike copy, there is no need for manual conversion with eduction):\n\njulia> table = StructVector(a = [1, 2, 3], b = [5, 6, 7]);\n\njulia> @assert tcopy(\n (A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a)\n ) == StructVector(A = [2, 4], B = [4, 6])\n\njulia> @assert tcopy(\n DataFrame,\n (A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a)\n ) == DataFrame(A = [2, 4], B = [4, 6])\n\njulia> @assert table |>\n Filter(row -> isodd(row.a)) |> Map(row -> (A = row.a + 1, B = row.b - 1)) |>\n tcopy == StructVector(A = [2, 4], B = [4, 6])\n\nIf you have Cat or MapCat at the end of the transducer, consider using foldxt directly:\n\njulia> using Transducers\n using DataFrames\n\njulia> @assert tcopy(\n DataFrame,\n 1:2 |> Map(x -> DataFrame(a = [x])) |> MapCat(eachrow);\n basesize = 1,\n ) == DataFrame(a = [1, 2])\n\njulia> using BangBang: Empty, append!!\n\njulia> @assert foldxt(\n append!!,\n Map(x -> DataFrame(a = [x])),\n 1:2;\n basesize = 1,\n # init = Empty(DataFrame),\n ) == DataFrame(a = [1, 2])\n\nNote that above snippet assumes that it is OK to mutate the dataframe returned by the transducer. Use init = Empty(DataFrame) if this is not the case.\n\nThis approach of using foldxt works with other containers; e.g., with TypedTables.Table:\n\njulia> using TypedTables\n\njulia> @assert foldxt(\n append!!,\n Map(x -> Table(a = [x])),\n 1:2;\n basesize = 1,\n # init = Empty(Table),\n ) == Table(a = [1, 2])\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.dcopy","page":"Manual","title":"Transducers.dcopy","text":"dcopy(xf::Transducer, T, reducible; [basesize, threads_basesize]) :: Union{T, Empty{T}}\ndcopy(xf::Transducer, reducible::T; [basesize, threads_basesize]) :: Union{T, Empty{T}}\ndcopy([T,] itr; [basesize, threads_basesize]) :: Union{T, Empty{T}}\n\nDistributed.jl-based parallel version of copy. Keyword arguments are passed to foldxd. For examples, see tcopy.\n\nSee also: Parallel processing tutorial (especially Example: parallel collect).\n\ncompat: Transducers.jl 0.4.5\nNew in version 0.4.5.\n\ncompat: Transducers.jl 0.4.8\ndcopy now accepts iterator comprehensions and eductions.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.append!","page":"Manual","title":"Base.append!","text":"append!(xf::Transducer, dest, src) -> dest\n\nThis API is modeled after into in Clojure.\n\nwarning: Warning\nThe performance of append!(dest, src::Eduction) is poor. Use append!! instead if two-argument form is preferred.\n\nExamples\n\njulia> using Transducers\n\njulia> append!(Drop(2), [-1, -2], 1:5)\n5-element Vector{Int64}:\n -1\n -2\n 3\n 4\n 5\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#BangBang.append!!","page":"Manual","title":"BangBang.append!!","text":"BangBang.append!!(xf::Transducer, dest, src) -> dest′\nBangBang.append!!(dest, src::Eduction) -> dest′\n\nMutate-or-widen version of append!.\n\ncompat: Transducers.jl 0.4.4\nNew in version 0.4.4.\n\ncompat: Transducers.jl 0.4.37\nPerformance optimization for append!!(dest, src::Eduction) requires version 0.4.37.\n\nExamples\n\njulia> using Transducers, BangBang\n\njulia> append!!(opcompose(Drop(2), Map(x -> x + 0.0)), [-1, -2], 1:5)\n5-element Vector{Float64}:\n -1.0\n -2.0\n 3.0\n 4.0\n 5.0\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.collect","page":"Manual","title":"Base.collect","text":"collect(xf::Transducer, itr) :: Vector\ncollect(ed::Eduction) :: Vector\n\nProcess an iterable itr using a transducer xf and collect the result into a Vector.\n\nFor parallel versions, see tcollect and dcollect.\n\ncompat: Transducers.jl 0.4.8\ncollect now accepts eductions.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Interpose(missing), 1:3)\n5-element Vector{Union{Missing, Int64}}:\n 1\n missing\n 2\n missing\n 3\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.tcollect","page":"Manual","title":"Transducers.tcollect","text":"tcollect(xf::Transducer, reducible; basesize) :: Union{Vector, Empty{Vector}}\ntcollect(itr; basesize) :: Union{Vector, Empty{Vector}}\n\nThread-based parallel version of collect. This is just a short-hand notation of tcopy(xf, Vector, reducible). Use tcopy to get a container other than a Vector.\n\nSee also: Parallel processing tutorial (especially Example: parallel collect).\n\ncompat: Transducers.jl 0.4.5\nNew in version 0.4.5.\n\ncompat: Transducers.jl 0.4.8\ntcollect now accepts iterator comprehensions and eductions.\n\nExamples\n\njulia> using Transducers\n\njulia> tcollect(Map(x -> x^2), 1:2)\n2-element Vector{Int64}:\n 1\n 4\n\njulia> tcollect(x^2 for x in 1:2)\n2-element Vector{Int64}:\n 1\n 4\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.dcollect","page":"Manual","title":"Transducers.dcollect","text":"dcollect(xf::Transducer, reducible; [basesize, threads_basesize]) :: Union{Vector, Empty{Vector}}\ndcollect(itr; [basesize, threads_basesize]) :: Union{Vector, Empty{Vector}}\n\nDistributed.jl-based parallel version of collect. This is just a short-hand notation of dcopy(xf, Vector, reducible). Use dcopy to get a container other than a Vector.\n\nSee also: Parallel processing tutorial (especially Example: parallel collect).\n\ncompat: Transducers.jl 0.4.5\nNew in version 0.4.5.\n\ncompat: Transducers.jl 0.4.8\ndcollect now accepts iterator comprehensions and eductions.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.Channel","page":"Manual","title":"Base.Channel","text":"Channel(xf::Transducer, itr; kwargs...)\nChannel(ed::Eduction; kwargs...)\n\nPipe items from an iterable itr processed by the transducer xf through a channel. Channel(xf, itr) and Channel(eduction(xf, itr)) are equivalent. Note that itr itself can be a Channel.\n\nKeyword arguments are passed to Channel(function; kwargs...).\n\nExamples\n\njulia> using Transducers\n\njulia> ch1 = Channel(Filter(isodd), 1:5);\n\njulia> ch2 = Channel(Map(x -> 2x - 1), ch1);\n\njulia> ed = eduction(Map(x -> 1:x), ch2);\n\njulia> ch3 = Channel(Cat(), ed);\n\njulia> foreach(PartitionBy(isequal(1)), ch3) do input\n @show input\n end;\ninput = [1, 1]\ninput = [2, 3, 4, 5]\ninput = [1]\ninput = [2, 3, 4, 5, 6, 7, 8, 9]\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Experimental-transducible-processes","page":"Manual","title":"Experimental transducible processes","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Transducers.channel_unordered\nTransducers.append_unordered!","category":"page"},{"location":"reference/manual/#Transducers.channel_unordered","page":"Manual","title":"Transducers.channel_unordered","text":"channel_unordered(xf, input; eltype, size, ntasks, basesize) :: Channel{eltype}\nchannel_unordered(itr; eltype, size, ntasks, basesize) :: Channel{eltype}\n\nProvide elements in input processed by a transducer xf through a Channel.\n\nUnary method channel_unordered(itr) produces a Channel that provides elements in the input iterator itr with possibly different order. Iterator comprehensions and eductions can be passed as the input itr.\n\nUse append_unordered! to send outputs to an existing channel.\n\ncompat: Transducers.jl 0.4.8\nNew in version 0.4.8.\n\ncompat: Transducers.jl 0.4.9\nUnary method channel_unordered(itr) requires Transducers.jl 0.4.9.\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nKeyword Arguments\n\neltype::Type: element type of returned channel\nsize: The size of Channel. A non-negative Int or Inf.\nntasks::Int: Number of concurrent tasks. Default to Threads.nthreads().\nbasesize: The \"batch size\" of the processing; i.e., the number of elements to be processed in a single task. Default to 1.\n\nExamples\n\njulia> using Transducers: Map, channel_unordered\n\njulia> sort!(collect(channel_unordered(Map(x -> x + 1), 1:3)))\n3-element Vector{Any}:\n 2\n 3\n 4\n\njulia> sort!(collect(channel_unordered(x + 1 for x in 1:3 if isodd(x))))\n2-element Vector{Any}:\n 2\n 4\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.append_unordered!","page":"Manual","title":"Transducers.append_unordered!","text":"append_unordered!(output, xf, input; ntasks, basesize)\nappend_unordered!(output, itr; ntasks, basesize)\n\nProcess input elements through a transducer xf and then push! them into output in undefined order.\n\nBinary method append_unordered!(output, itr) is like append!(output, itr) but without order guarantee. Iterator comprehensions and eductions can be passed as the input itr.\n\noutput (typically a Channel) must implement thread-safe push!(output, x) method.\n\nSee also channel_unordered.\n\ncompat: Transducers.jl 0.4.8\nNew in version 0.4.8.\n\ncompat: Transducers.jl 0.4.9\nBinary method append_unordered!(output, itr) requires Transducers.jl 0.4.9.\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nExamples\n\njulia> using Transducers: Map, append_unordered!\n\njulia> input = Channel(Map(identity), 1:3);\n\njulia> output = Channel{Int}(0);\n\njulia> task = @async try\n append_unordered!(output, Map(x -> x + 1), input)\n finally\n close(output)\n end;\n\njulia> sort!(collect(output))\n3-element Vector{Int64}:\n 2\n 3\n 4\n\njulia> input = Channel(Map(identity), 1:3);\n\njulia> output = Channel{Int}(0);\n\njulia> task = @async try\n append_unordered!(output, (y for x in input if isodd(x) for y in 1:x))\n finally\n close(output)\n end;\n\njulia> sort!(collect(output))\n4-element Vector{Int64}:\n 1\n 1\n 2\n 3\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers","page":"Manual","title":"Transducers","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Transducers.Transducer\nCompositionsBase.:⨟\nBase.:∘\nBase.adjoint","category":"page"},{"location":"reference/manual/#Transducers.Transducer","page":"Manual","title":"Transducers.Transducer","text":"Transducer\n\nThe abstract type for transducers.\n\nA transducer xf can be used as both iterator transformation xf(itr) and reducing function transformation xf'(rf).\n\nSee also adjoint for xf'(rf).\n\ncompat: Transducers.jl 0.4.39\nThe call overload xf(rf) requires Transducers.jl 0.4.39 or later.\n\nnote: Note\nThe call overload xf(rf) requires Julia 1.3 or later. For older Julia versions, use eduction.\n\nExamples\n\njulia> using Transducers\n\njulia> xs = Map(inv)(2:2:4)\n2-element StepRange{Int64, Int64} |>\n Map(inv)\n\njulia> collect(xs)\n2-element Vector{Float64}:\n 0.5\n 0.25\n\njulia> rf = Map(inv)'(+)\nReduction(\n Map(inv),\n BottomRF(\n +))\n\njulia> rf(1, 4) # +(1, inv(4))\n1.25\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#CompositionsBase.:⨟","page":"Manual","title":"CompositionsBase.:⨟","text":"g ⨟ f\nopcompose(g, f)\n\nThe opposite composition operator defined as\n\ng ⨟ f = f ∘ g\n⨟(f) = f\n⨟(fs...) = ∘(reverse(fs)...)\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.:∘","page":"Manual","title":"Base.:∘","text":"f ⨟ g\ng ∘ f\nopcompose(f, g)\ncompose(g, f)\n\nComposition of transducers.\n\ncompat: Transducers.jl 0.4.39\nTransducers.jl 0.4.39 or later is required for composing transducers with ∘ and other operators and functions derived from it.Transducers written as f |> g |> h in previous versions of Transducers.jl can now be written as f ⨟ g ⨟ h (in Julia 1.5 or later) or opcompose(f, g, h).\n\nnote: Note\n\"op\" in opcompose does not stand for operator; it stands for opposite.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.adjoint","page":"Manual","title":"Base.adjoint","text":"xf'\n\nxf'(rf₁) is a shortcut for calling reducingfunction(xf, rf₁).\n\nMore precisely, adjoint xf′ of a transducer xf is a reducing function transform rf₁ -> rf₂. That is to say, xf' a function that maps a reducing function rf₁ to another reducing function rf₂.\n\nExamples\n\njulia> using Transducers\n\njulia> y = Map(inv)'(+)(10, 2)\n10.5\n\njulia> y == +(10, inv(2))\ntrue\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Modules = [Transducers]\nPrivate = false\nFilter = Transducers.is_transducer_type","category":"page"},{"location":"reference/manual/#Transducers.Broadcasting","page":"Manual","title":"Transducers.Broadcasting","text":"Broadcasting()\n\nBroadcast inner reducing function over elements in the input. Roughly speaking, it transforms the inner reducing function op to op′(a, b) = op.(a, b). However, it has a better memory usage and better initial value handling.\n\nIf the input is an array, the array created at the first iteration is reused if it can hold the element types of subsequent iterations. Otherwise, the array type is widen as needed.\n\nIf init passed to the fold function is a lazy \"initializer\" object such as OnInit, it is initialized independently for each item in the first input array. This makes using Broadcasting for (possibly) in-place functions safe.\n\ncompat: Transducers.jl 0.4.32\nNew in version 0.4.32.\n\nnote: Note\nBroadcasting transducer is not supported in Julia 1.0.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(+, Broadcasting(), [[1, 2], [3, 4], 5])\n2-element Vector{Int64}:\n 9\n 11\n\njulia> foldl(+, Broadcasting(), [(0,), [1], [2.0], [3 + 0im]])\n1-element Vector{ComplexF64}:\n 6.0 + 0.0im\n\njulia> foldl(\n *,\n [[[1], [10, 100]], [[2], [20, 200]], [[3], [30, 300]]] |>\n Broadcasting() |> Broadcasting(),\n )\n2-element Vector{Vector{Int64}}:\n [6]\n [6000, 6000000]\n\nWhen processing nested data structure (e.g., array-of-arrays) and mutating accumulator in-place, be careful with sharing the accumulators with each processing of items in the input. For example, this is a bad example:\n\njulia> add!(a, b) = a .+= b;\n\njulia> foldl(add!, Broadcasting(), [[[1], [2, 3]], [[4, 5], 6]];\n init = Ref([0, 0]))\n2-element Vector{Vector{Int64}}:\n [13, 15]\n [13, 15]\n\njulia> ans[1] === ans[2] # they are the same object\ntrue\n\nUse OnInit to initialize a new array with each item in the input:\n\njulia> foldl(add!, Broadcasting(), [[[1], [2, 3]], [[4, 5], 6]];\n init = OnInit(() -> [0, 0]))\n2-element Vector{Vector{Int64}}:\n [5, 6]\n [8, 9]\n\njulia> ans == [\n add!(add!([0, 0], [1]), [4, 5]),\n add!(add!([0, 0], [2, 3]), 6),\n ]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Cat","page":"Manual","title":"Transducers.Cat","text":"Cat()\n\nConcatenate/flatten nested iterators.\n\nThis API is modeled after cat in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Cat(), [[1, 2], [3], [4, 5]]) == 1:5\ntrue\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Consecutive","page":"Manual","title":"Transducers.Consecutive","text":"Consecutive(size, step = size)\nConsecutive(size; step = size)\n\nSliding window of width size and interval step. Yield tuples.\n\nThis transducer is like Partition but feeds tuples to the downstream transducers instead of vectors.\n\nIf step == 1, this transducer supports parallel reduction for any collections; i.e., Consecutive(size, 1)'(op) is associative if op is associative.\n\nwarning: Warning\nCurrently, in parallel folds, Consecutive(size, 1) cannot be used with reducing functions that can produce a Reduced.\n\nIf step > 1, this transducer can, in principle, support parallel reduction if the input collection allows random access (e.g., arrays). However, this feature is not implemented yet.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:8 |> Consecutive(3) |> collect\n2-element Vector{Tuple{Int64, Int64, Int64}}:\n (1, 2, 3)\n (4, 5, 6)\n\njulia> 1:8 |> Consecutive(3; step = 1) |> collect\n6-element Vector{Tuple{Int64, Int64, Int64}}:\n (1, 2, 3)\n (2, 3, 4)\n (3, 4, 5)\n (4, 5, 6)\n (5, 6, 7)\n (6, 7, 8)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Count","page":"Manual","title":"Transducers.Count","text":"Count([start[, step]])\n\nGenerate a sequence start, start + step, start + step + step, and so on.\n\nNote that input is ignored. To use the input in the downstream reduction steps, use Zip.\n\nstart defaults to 1 and step defaults to oneunit(start).\n\nSee also: Iterators.countfrom. Enumerate\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Zip(Map(identity), Count()), -3:-1)\n3-element Vector{Tuple{Int64, Int64}}:\n (-3, 1)\n (-2, 2)\n (-1, 3)\n\njulia> using Dates\n\njulia> 1:3 |> Zip(Map(identity), Count(Day(1))) |> MapSplat(*) |> collect ==\n [Day(1), Day(4), Day(9)]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Dedupe","page":"Manual","title":"Transducers.Dedupe","text":"Dedupe()\nDedupe(eq)\n\nDe-duplicate consecutive items. Comparison operator which identifies duplicates can be specified by the eq parameter, which defaults to == (equal).\n\nThis API is modeled after dedupe in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Dedupe(), [1, 1, 2, 1, 3, 3, 2])\n5-element Vector{Int64}:\n 1\n 2\n 1\n 3\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Drop","page":"Manual","title":"Transducers.Drop","text":"Drop(n)\n\nDrop first n items.\n\nThis API is modeled after drop in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:5 |> Drop(3) |> collect\n2-element Vector{Int64}:\n 4\n 5\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.DropLast","page":"Manual","title":"Transducers.DropLast","text":"DropLast(n)\n\nDrop last n items.\n\nThis API is modeled after drop-last in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:5 |> DropLast(2) |> collect\n3-element Vector{Int64}:\n 1\n 2\n 3\n\njulia> 1:1 |> DropLast(2) |> collect == []\ntrue\n\njulia> 1:0 |> DropLast(2) |> collect == []\ntrue\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.DropWhile","page":"Manual","title":"Transducers.DropWhile","text":"DropWhile(pred)\n\nDrop items while pred returns true consecutively. It becomes a no-op after pred returns a false.\n\nThis API is modeled after drop-while in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(DropWhile(x -> x < 3), [1:5; 1:2])\n5-element Vector{Int64}:\n 3\n 4\n 5\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Enumerate","page":"Manual","title":"Transducers.Enumerate","text":"Enumerate([start[, step]])\n\nTransducer variant of Base.enumerate. The start and step arguments are optional and have the same meaning as in Count.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Enumerate(), [\"A\", \"B\", \"C\"])\n3-element Vector{Tuple{Int64, String}}:\n (1, \"A\")\n (2, \"B\")\n (3, \"C\")\n\njulia> start=2; step=3;\n\njulia> collect(Enumerate(start, step), [\"A\", \"B\", \"C\"])\n3-element Vector{Tuple{Int64, String}}:\n (2, \"A\")\n (5, \"B\")\n (8, \"C\")\n\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Filter","page":"Manual","title":"Transducers.Filter","text":"Filter(pred)\n\nSkip items for which pred is evaluated to false.\n\nThis API is modeled after filter in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:3 |> Filter(iseven) |> collect\n1-element Vector{Int64}:\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.FlagFirst","page":"Manual","title":"Transducers.FlagFirst","text":"FlagFirst()\n\nOutput (isfirst, input) where isfirst::Bool is true only for the first iteration and input is the original input.\n\nSee also: IterTools.flagfirst\n\nExamples\n\njulia> using Transducers\n\njulia> collect(FlagFirst(), 1:3)\n3-element Vector{Tuple{Bool, Int64}}:\n (1, 1)\n (0, 2)\n (0, 3)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.GroupBy","page":"Manual","title":"Transducers.GroupBy","text":"GroupBy(key, xf::Transducer, [step = right, [init]])\nGroupBy(key, rf, [init])\n\nGroup the input stream by a function key and then fan-out each group of key-value pairs to the eduction xf'(step). This is similar to the groupby relational database operation.\n\nFor example\n\n[1,2,1,2,3] |> GroupBy(string, Map(last)'(+)) |> foldxl(right)\n\nreturns a result equivalent to Dict(\"1\"=>2, \"2\"=>4, \"3\"=>3) while\n\n[1,2,1,2,3] |> GroupBy(string, Map(last) ⨟ Map(Transducers.SingletonVector), append!!) |> foldxl(right)\n\nreturns a result equivalent to Dict(\"1\"=>[1,1], \"2\"=>[2,2], \"3\"=>[3,3]).\n\nAlternatively, one can provide a reducing function directly, though this is disfavored since it prevents results from being combined with Transducers.combine and therefore cannot be used with foldxt or foldxd. For example, if GroupBy is used as in:\n\nxs |> Map(upstream) |> GroupBy(key, rf, init) |> Map(downstream)\n\nthen the function signatures would be:\n\nupstream(_) :: V\nkey(::V) :: K\nrf(::Y, ::Pair{K, V}) ::Y\ndownstream(::Dict{K, Y})\n\nThat is to say,\n\nOuput of the upstream is fed into the function key that produces the group key (of type K).\nFor each new group key, a new transducible process is started with the initial state init :: Y. Pass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each group.\nAfter one \"nested\" reducing function rf is called, the intermediate result dictionary (of type Dict{K, Y}) accumulating the current and all preceding results is then fed into the downstream.\n\nSee also groupreduce in SplitApplyCombine.jl.\n\nExamples\n\njulia> [1,2,3,4] |> GroupBy(iseven, Map(last)'(+)) |> foldxl(right)\nTransducers.GroupByViewDict{Bool,Int64,…}(...):\n 0 => 4\n 1 => 6\n\njulia> using Transducers: SingletonDict;\n\njulia> using BangBang; # for merge!!\n\njulia> x = [(a=\"A\", b=1, c=1), (a=\"B\", b=2, c=2), (a=\"A\", b=3, c=3)];\n\njulia> inner = Map(last) ⨟ Map() do ξ\n SingletonDict(ξ.b => ξ.c)\n end;\n\njulia> x |> GroupBy(ξ -> ξ.a, inner, merge!!) |> foldxl(right)\nTransducers.GroupByViewDict{String,Dict{Int64, Int64},…}(...):\n \"B\" => Dict(2=>2)\n \"A\" => Dict(3=>3, 1=>1)\n\nNote that the reduction stops if one of the group returns a reduced. This can be used, for example, to find if there is a group with a sum grater than 3 and stop the computation as soon as it is find:\n\njulia> result = transduce(\n GroupBy(\n string,\n Map(last) ⨟ Scan(+) ⨟ ReduceIf(x -> x > 3),\n ),\n right,\n nothing,\n [1, 2, 1, 2, 3],\n );\n\njulia> result isa Reduced\ntrue\n\njulia> unreduced(result)\nTransducers.GroupByViewDict{String,Any,…}(...):\n \"1\" => 2\n \"2\" => 4\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Interpose","page":"Manual","title":"Transducers.Interpose","text":"Interpose(sep)\n\nInterleave input items with a sep.\n\nThis API is modeled after interpose in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Interpose(missing), 1:3)\n5-element Vector{Union{Missing, Int64}}:\n 1\n missing\n 2\n missing\n 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Iterated","page":"Manual","title":"Transducers.Iterated","text":"Iterated(f, init)\n\nGenerate a sequence init, f(init), f(f(init)), f(f(f(init))), and so on.\n\nNote that input is ignored. To use the input in the downstream reduction steps, use Zip.\n\nPass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.\n\nSee also: Scan, ScanEmit.\n\nThe idea is taken from IterTools.iterated\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Iterated(x -> 2x, 1), 1:5)\n5-element Vector{Int64}:\n 1\n 2\n 4\n 8\n 16\n\njulia> collect(Zip(Map(identity), Iterated(x -> 2x, 1)), 1:5)\n5-element Vector{Tuple{Int64, Int64}}:\n (1, 1)\n (2, 2)\n (3, 4)\n (4, 8)\n (5, 16)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.KeepSomething","page":"Manual","title":"Transducers.KeepSomething","text":"KeepSomething(f = identity)\n\nPass non-nothing output of f to the inner reducing step after possibly unwrapping Some.\n\nThis API is modeled after keep in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> xf = KeepSomething() do x\n if x == 0\n :zero\n elseif x == 1\n Some(:one)\n elseif x == 2\n Some(nothing)\n end\n end;\n\njulia> collect(xf, 0:3)\n3-element Vector{Union{Nothing, Symbol}}:\n :zero\n :one\n nothing\n\nNote that NotA(Nothing) can be used to avoid automatically unwrapping Some:\n\njulia> [Some(1), 2, nothing] |> KeepSomething() |> collect\n2-element Vector{Int64}:\n 1\n 2\n\njulia> [Some(1), 2, nothing] |> NotA(Nothing) |> collect\n2-element Vector{Any}:\n Some(1)\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Map","page":"Manual","title":"Transducers.Map","text":"Map(f)\n\nApply unary function f to each input and pass the result to the inner reducing step.\n\nThis API is modeled after map in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Map(x -> 2x), 1:3)\n3-element Vector{Int64}:\n 2\n 4\n 6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.MapCat","page":"Manual","title":"Transducers.MapCat","text":"MapCat(f)\n\nConcatenate output of f which is expected to return an iterable.\n\nThis API is modeled after mapcat in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(MapCat(x -> 1:x), 1:3)\n6-element Vector{Int64}:\n 1\n 1\n 2\n 1\n 2\n 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.MapSplat","page":"Manual","title":"Transducers.MapSplat","text":"MapSplat(f)\n\nLike Map(f) but calls f(input...) for each input and then pass the result to the inner reducing step.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(MapSplat(*), zip(1:3, 10:10:30))\n3-element Vector{Int64}:\n 10\n 40\n 90\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.NondeterministicThreading","page":"Manual","title":"Transducers.NondeterministicThreading","text":"NondeterministicThreading(; basesize, ntasks = nthreads())\n\nParallelize inner reducing function using ntasks.\n\nGiven\n\n# ,-- Not parallelized\n# ______/__\n foldxl(rf, xs |> xfo |> NondeterministicThreading() |> xfi)\n# == ===\n# Parallelized Parallelized\n\nthe inner transducer xfi and the reducing function rf are parallelized but the outer transducer xfo and the iteration over data collection xs are not parallelized.\n\nThe scheduling of the tasks (hence the call tree of the inner reducing function) is non-deterministic. It means that the result is deterministic only if the inner reducing function is exactly associative. If the inner reducing function is only approximately associative (e.g., addition of floating point numbers), the result of reduction is likely different for each time.\n\nThe outer transducers and iterate are processed sequentially. In particular, the data collection does not have to implement SplittablesBase.halve.\n\nnote: Note\nCurrently, the default basesize is 1. However, it may be changed in the future (e.g. it may be automatically tuned at run-time).\n\nnote: Note\nNondeterministicThreading does not work with Julia < 1.3.\n\nKeyword Arguments\n\nbasesize::Integer: The number of input elements to be accumulated in a buffer before sent to a task.\nntasks::Integer: The number of tasks @spawned. The default value is Threads.nthreads(). A number larger than Threads.nthreads() may be useful if the inner reducing function contains I/O and does not consume too much resource (e.g., memory).\n\nExamples\n\njulia> using Transducers\n\njulia> collect(1:4 |> Filter(isodd))\n2-element Vector{Int64}:\n 1\n 3\n\njulia> collect(1:4 |> NondeterministicThreading() |> Filter(isodd))\n2-element Vector{Int64}:\n 1\n 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.NotA","page":"Manual","title":"Transducers.NotA","text":"NotA(T)\n\nSkip items of type T. Unlike Filter(!ismissing), downstream transducers can have a correct type information for NotA(Missing).\n\nSee also: OfType\n\nExamples\n\njulia> using Transducers\n\njulia> [1, missing, 2] |> NotA(Missing) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.OfType","page":"Manual","title":"Transducers.OfType","text":"OfType(T)\n\nInclude only items of type T.\n\nSee also: NotA\n\nExamples\n\njulia> using Transducers\n\njulia> [1, missing, 2] |> OfType(Int) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Partition","page":"Manual","title":"Transducers.Partition","text":"Partition(size, step = size, flush = false)\nPartition(size; step = size, flush = false)\n\nSliding window of width size and interval step. Yield vectors.\n\nNote: step = size is the default. Hence, the default behavior is non-overlapping windows.\n\nFor small size, see Consecutive for a similar transducer that yields tuples instead.\n\nwarning: Warning\nThe vector passed to the inner reducing function is valid only during its immediate reduction step. It must be reduced immediately or copied.\n\nThis API is modeled after partition-all in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:8 |> Partition(3) |> Map(copy) |> collect\n2-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [4, 5, 6]\n\njulia> 1:8 |> Partition(3; flush=true) |> Map(copy) |> collect\n3-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [4, 5, 6]\n [7, 8]\n\njulia> 1:8 |> Partition(3; step=1) |> Map(copy) |> collect\n6-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [2, 3, 4]\n [3, 4, 5]\n [4, 5, 6]\n [5, 6, 7]\n [6, 7, 8]\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.PartitionBy","page":"Manual","title":"Transducers.PartitionBy","text":"PartitionBy(f)\n\nGroup input sequence into chunks in which f returns a same value consecutively.\n\nwarning: Warning\nThe vector passed to the inner reducing function is valid only during its immediate reduction step. It must be reduced immediately or copied.\n\nThis API is modeled after partition-by in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:9 |> PartitionBy(x -> (x + 1) ÷ 3) |> Map(copy) |> collect\n4-element Vector{UnitRange{Int64}}:\n 1:1\n 2:4\n 5:7\n 8:9\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.ReduceIf","page":"Manual","title":"Transducers.ReduceIf","text":"ReduceIf(pred)\n\nStop fold when pred(x) returns true for the output x of the upstream transducer.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(right, ReduceIf(x -> x == 3), 1:10)\n3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.ReducePartitionBy","page":"Manual","title":"Transducers.ReducePartitionBy","text":"ReducePartitionBy(f, rf, [init])\n\nReduce partitions determined by isequal on the output value of f with an associative reducing function rf. Partitions are reduced on-the-fly and no intermediate arrays are allocated.\n\nExamples\n\nConsider the input 1:6 \"keyed\" by a function x -> x ÷ 3:\n\njulia> map(x -> x ÷ 3, 1:6)\n6-element Vector{Int64}:\n 0\n 0\n 1\n 1\n 1\n 2\n\ni.e., there are three partitions with the key values 0, 1, and 2. We can use ReducePartitionBy to compute, e.g., the length and the sum of each partition by:\n\njulia> using Transducers\n\njulia> 1:6 |> ReducePartitionBy(x -> x ÷ 3, Map(_ -> 1)'(+)) |> collect\n3-element Vector{Int64}:\n 2\n 3\n 1\n\njulia> 1:6 |> ReducePartitionBy(x -> x ÷ 3, +) |> collect\n3-element Vector{Int64}:\n 3\n 12\n 6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Replace","page":"Manual","title":"Transducers.Replace","text":"Replace(assoc)\n\nReplace each input with the value in the associative container assoc (e.g., a dictionary, array, string) if it matches with a key/index. Otherwise output the input as-is.\n\nThis API is modeled after replace in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Replace(Dict('a' => 'A')), \"abc\")\n3-element Vector{Char}:\n 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n\njulia> collect(Replace([:a, :b, :c]), 0:4)\n5-element Vector{Any}:\n 0\n :a\n :b\n :c\n 4\n\njulia> collect(Replace(\"abc\"), 0:4)\n5-element Vector{Any}:\n 0\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 4\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Scan","page":"Manual","title":"Transducers.Scan","text":"Scan(f, [init = Init])\n\nAccumulate input with binary function f and pass the accumulated result so far to the inner reduction step.\n\nThe inner reducing step receives the sequence y₁, y₂, y₃, ..., yₙ, ... when the sequence x₁, x₂, x₃, ..., xₙ, ... is fed to Scan(f).\n\ny₁ = f(init, x₁)\ny₂ = f(y₁, x₂)\ny₃ = f(y₂, x₃)\n...\nyₙ = f(yₙ₋₁, xₙ)\n\nThis is a generalized version of the prefix sum also known as cumulative sum, inclusive scan, or scan.\n\nNote that the associativity of f is not required when the transducer is used in a process that guarantee an order, such as foldl.\n\nUnless f is a function with known identity element such as +, *, min, max, and append!, the initial state init must be provided.\n\nPass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.\n\nSee also: ScanEmit, Iterated.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Scan(*), 1:3)\n3-element Vector{Int64}:\n 1\n 2\n 6\n\njulia> 1:3 |> Map(x -> x + im) |> Scan(*) |> collect\n3-element Vector{Complex{Int64}}:\n 1 + 1im\n 1 + 3im\n 0 + 10im\n\njulia> collect(Scan(*, 10), 1:3)\n3-element Vector{Int64}:\n 10\n 20\n 60\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.ScanEmit","page":"Manual","title":"Transducers.ScanEmit","text":"ScanEmit(f, init[, onlast])\n\nAccumulate input x with a function f with the call signature (u, x) -> (y, u) and pass the result y to the inner reduction step.\n\nThe inner reducing step receives the sequence y₁, y₂, y₃, ..., yₙ, ... computed as follows\n\nu₀ = init\ny₁, u₁ = f(u₀, x₁)\ny₂, u₂ = f(u₁, x₂)\ny₃, u₃ = f(u₂, x₃)\n...\nyₙ, uₙ = f(uₙ₋₁, xₙ)\n...\nyₒₒ = onlast(uₒₒ)\n\nwhen the sequence x₁, x₂, x₃, ..., xₙ, ... is fed to ScanEmit(f).\n\nPass OnInit or CopyInit object to init for creating a dedicated (possibly mutable) state for each fold.\n\nSee also: Scan, Iterated.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(ScanEmit(tuple, 0), 1:3)\n3-element Vector{Int64}:\n 0\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.TCat","page":"Manual","title":"Transducers.TCat","text":"TCat(basesize::Integer)\n\nThreaded version of Cat (concatenate/flatten).\n\nTo use this transducer, all the downstream (inner) transducers must be stateless (or of type ScanEmit) and the reducing function must be associative. See also: Parallel processing tutorial.\n\nNote that the upstream (outer) transducers need not to be stateless as long as it is called with non-parallel reduction such as foldl and collect.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:3 |> Map(x -> 1:x) |> TCat(1) |> tcollect\n6-element Vector{Int64}:\n 1\n 1\n 2\n 1\n 2\n 3\n\njulia> 1:3 |> Scan(+) |> Map(x -> 1:x) |> TCat(1) |> collect\n10-element Vector{Int64}:\n 1\n 1\n 2\n 3\n 1\n 2\n 3\n 4\n 5\n 6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Take","page":"Manual","title":"Transducers.Take","text":"Take(n)\n\nTake n items from the input sequence.\n\nThis API is modeled after take in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:10 |> Take(2) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\njulia> 1:2 |> Take(5) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\nUsing a low-level API, it's possible to distinguish if the output is truncated or not:\n\njulia> transduce(Take(3), Completing(push!!), Init, 1:2)\n2-element Vector{Int64}:\n 1\n 2\n\njulia> transduce(Take(3), Completing(push!!), Init, 1:4)\nReduced([1, 2, 3])\n\njulia> transduce(Take(3), Completing(push!!), Init, 1:0)\nInitialValue(push!!)\n\nSee also transduce, Reduced and Completing.\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.TakeLast","page":"Manual","title":"Transducers.TakeLast","text":"TakeLast(n)\n\nTake last n items from the input sequence.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:10 |> TakeLast(2) |> collect\n2-element Vector{Int64}:\n 9\n 10\n\njulia> 1:2 |> TakeLast(5) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.TakeNth","page":"Manual","title":"Transducers.TakeNth","text":"TakeNth(n)\n\nOutput every n item to the inner reducing step.\n\nThis API is modeled after take-nth in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> 1:9 |> TakeNth(3) |> collect\n3-element Vector{Int64}:\n 1\n 4\n 7\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.TakeWhile","page":"Manual","title":"Transducers.TakeWhile","text":"TakeWhile(pred)\n\nTake items while pred returns true. Abort the reduction when pred returns false for the first time.\n\nThis API is modeled after take-while in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> [1, 2, 3, 1, 2] |> TakeWhile(x -> x < 3) |> collect\n2-element Vector{Int64}:\n 1\n 2\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Unique","page":"Manual","title":"Transducers.Unique","text":"Unique(by = identity)\n\nPass only unseen item to the inner reducing step.\n\nThe item is distinguished by the output of function by when given.\n\nThis API is modeled after distinct in Clojure.\n\ncompat: Transducers.jl 0.4.2\nNew in version 0.4.2.\n\nExamples\n\njulia> using Transducers\n\njulia> [1, 1, 2, -1, 3, 3, 2] |> Unique() |> collect\n4-element Vector{Int64}:\n 1\n 2\n -1\n 3\n\njulia> [1, 1, 2, -1, 3, 3, 2] |> Unique(x -> x^2) |> collect\n3-element Vector{Int64}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Zip-Tuple","page":"Manual","title":"Transducers.Zip","text":"Zip(xforms...)\n\nZip outputs of transducers xforms in a tuple and pass it to the inner reduction step.\n\nwarning: Warning\nHead transducers drive tail transducers. Be careful when using it with transducers other than Map, especially the contractive ones like PartitionBy and the expansive ones like MapCat.\n\nExamples\n\njulia> using Transducers\n\njulia> collect(Zip(Map(identity), Map(x -> 10x), Map(x -> 100x)), 1:3)\n3-element Vector{Tuple{Int64, Int64, Int64}}:\n (1, 10, 100)\n (2, 20, 200)\n (3, 30, 300)\n\n\n\n\n\n","category":"method"},{"location":"reference/manual/#Experimental-transducers","page":"Manual","title":"Experimental transducers","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Transducers.ZipSource\nTransducers.GetIndex\nTransducers.SetIndex\nTransducers.Inject","category":"page"},{"location":"reference/manual/#Transducers.ZipSource","page":"Manual","title":"Transducers.ZipSource","text":"ZipSource(xform::Transducer)\n\nBranch input into two \"flows\", inject one into xform and then merge (zip) the output of xform with the original (source) input.\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nTo illustrate how it works, consider the following usage\n\ncollection |> xf0 |> ZipSource(xf1) |> xf2\n\nwhere xf0, xf1, and xf2 are some transducers. Schematically, the output yn from xfn flows as follows:\n\nxf0 xf1 xf2\n---- y0 ------ y1 ---.-- (y0, y1) ----->\n | |\n `-------------'\n\nExamples\n\njulia> using Transducers\n using Transducers: ZipSource\n\njulia> collect(ZipSource(opcompose(Filter(isodd), Map(x -> x + 1))), 1:5)\n3-element Vector{Tuple{Int64, Int64}}:\n (1, 2)\n (3, 4)\n (5, 6)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.GetIndex","page":"Manual","title":"Transducers.GetIndex","text":"GetIndex(array)\nGetIndex{inbounds}(array)\n\nTransform an integer input i to array[i].\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nExamples\n\njulia> using Transducers\n using Transducers: GetIndex\n\njulia> collect(GetIndex('a':'z'), [2, 3, 4])\n3-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\njulia> collect(GetIndex{true}('a':'z'), [2, 3, 4]) # Inbounds\n3-element Vector{Char}:\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.SetIndex","page":"Manual","title":"Transducers.SetIndex","text":"SetIndex(array)\nSetIndex{inbounds}(array)\n\nPerform array[i] = v for each input pair (i, v).\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nExamples\n\njulia> using Transducers\n using Transducers: SetIndex\n\njulia> ys = zeros(3);\n\njulia> foldl(first ∘ tuple, SetIndex(ys), [(1, 11.1), (3, 33.3)], init=nothing)\n\njulia> ys\n3-element Vector{Float64}:\n 11.1\n 0.0\n 33.3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Inject","page":"Manual","title":"Transducers.Inject","text":"Inject(iterator)\n\nInject the output from iterator to the stream processed by the inner reduction step.\n\nwarning: Warning\nThis API is experimental. Backward incompatible change, including the removal of this API, is more likely to occur than other parts of this package.\n\nExamples\n\njulia> using Transducers\n using Transducers: Inject\n\njulia> collect(Inject(Iterators.cycle(\"hello\")), 1:8)\n8-element Vector{Tuple{Int64, Char}}:\n (1, 'h')\n (2, 'e')\n (3, 'l')\n (4, 'l')\n (5, 'o')\n (6, 'h')\n (7, 'e')\n (8, 'l')\n\njulia> collect(Inject(Iterators.repeated([1 2])), 1:4)\n4-element Vector{Tuple{Int64, Matrix{Int64}}}:\n (1, [1 2])\n (2, [1 2])\n (3, [1 2])\n (4, [1 2])\n\njulia> collect(Inject(Iterators.product(1:2, 3:5)), 1:100)\n6-element Vector{Tuple{Int64, Tuple{Int64, Int64}}}:\n (1, (1, 3))\n (2, (2, 3))\n (3, (1, 4))\n (4, (2, 4))\n (5, (1, 5))\n (6, (2, 5))\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#combinators","page":"Manual","title":"Other reducing function combinators","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Transducers.TeeRF\nTransducers.ProductRF\nTransducers.wheninit\nTransducers.whenstart\nTransducers.whencomplete\nTransducers.whencombine","category":"page"},{"location":"reference/manual/#Transducers.TeeRF","page":"Manual","title":"Transducers.TeeRF","text":"TeeRF(reducing_functions::Tuple)\nTeeRF(reducing_functions...)\n\nCombine multiple reducing functions into a new reducing function that \"multicast\" the input to multiple reducing functions.\n\nRoughly speaking, TeeRF(op₁, op₂, ..., opₙ) is equivalent to\n\n((a₁, a₂, ..., aₙ), x) -> (op₁(a₁, x), op₂(a₂, x), ..., opₙ(aₙ, x))\n\nFor combine, it behaves like ProductRF.\n\ncompat: Transducers.jl 0.4.32\nNew in version 0.4.32.\n\nExamples\n\njulia> using Transducers\n\njulia> extrema′(xs, xf = Map(identity)) = foldl(TeeRF(min, max), xf, xs);\n\njulia> extrema′([5, 2, 6, 8, 3])\n(2, 8)\n\nNote that the input is considered empty unless all reducing functions call their bottom reducing functions. Specify init to obtain results even when the input collection is empty or all filtered out.\n\njulia> filtering_max = Filter(isodd)'(max);\n\njulia> foldl(TeeRF(min, filtering_max), Map(identity), [5, 2, 6, 8, 3])\n(2, 5)\n\njulia> foldl(TeeRF(min, filtering_max), Map(identity), 2:2:8)\nERROR: EmptyResultError: ...\n\njulia> foldl(TeeRF(min, filtering_max), Map(identity), 2:2:8; init = Init)\n(2, InitialValue(max))\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.ProductRF","page":"Manual","title":"Transducers.ProductRF","text":"ProductRF(reducing_functions::Tuple)\nProductRF(reducing_functions...)\n\nCombine N reducing functions into a new reducing function that work on N-tuple. The i-th reducing function receives the i-th element of the input tuple.\n\nRoughly speaking, ProductRF(op₁, op₂, ..., opₙ) is equivalent to\n\n((a₁, a₂, ..., aₙ), (b₁, b₂, ..., bₙ)) -> (op₁(a₁, b₁), op₂(a₂, b₂), ..., opₙ(aₙ, bₙ))\n\ncompat: Transducers.jl 0.4.32\nNew in version 0.4.32.\n\nExamples\n\nLike TeeRF, ProductRF can be used to drive multiple reducing functions. ProductRF is more \"low-level\" in the sense that TeeRF can be defined in terms of ProductRF (other direction is much harder):\n\njulia> using Transducers\n\njulia> TeeRF′(fs...) = reducingfunction(\n Map(x -> ntuple(_ -> x, length(fs))),\n ProductRF(fs...),\n );\n\njulia> foldl(TeeRF′(min, max), Map(identity), [5, 2, 6, 8, 3])\n(2, 8)\n\nProductRF may be useful for handling pre-existing stream whose item type is already a tuple:\n\njulia> foldl(ProductRF(&, +), Map(x -> (isodd(x), x)), [5, 2, 6, 8, 3])\n(false, 24)\n\njulia> foldl(TeeRF(reducingfunction(Map(isodd), &), +), Map(identity), [5, 2, 6, 8, 3])\n(false, 24)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.wheninit","page":"Manual","title":"Transducers.wheninit","text":"wheninit(oninit, rf) -> rf′\nwheninit(oninit) -> rf -> rf′\nwhenstart(start, rf) -> rf′\nwhenstart(start) -> rf -> rf′\nwhencomplete(complete, rf) -> rf′\nwhencomplete(complete) -> rf -> rf′\nwhencombine(combine, rf) -> rf′\nwhencombine(combine) -> rf -> rf′\n\nAdd initialization/completion/merging phase to arbitrary reducing function.\n\nThe functions passed to those combinators are used as follows in foldl:\n\ninit′ = oninit() # if oninit is given; otherwise standard `init`-preprocessing\nacc = start(init′)\nfor x in collection\n acc += rf(acc, x)\nend\nresult = acc\nreturn complete(result)\n\nIn foldxt, a collection is split in multiple parts and then above foldl except for complete is run on them, yielding multiple results which are combined by repeatedly calling combine(result_1, result_2). Note that this allows non-associative function for next while combine must be associative.\n\nSee also next, start, complete, and combine.\n\nArguments\n\nrf: reducing function\noninit: nullary function that generates an initial value for rf\nstart: unary function that pre-process the initial value for rf\ncomplete: unary function that post-process the accumulator\ncombine: (approximately) associative binary function for combining multiple results of rf (before post-processed by complete).\n\nExtended help\n\nExamples\n\nAn example for using non-associative reducing function in foldxt:\n\njulia> using Transducers\n\njulia> collector! = push! |> whencombine(append!) |> wheninit(() -> []);\n\njulia> foldxt(collector!, Filter(isodd), 1:5; basesize = 1)\n3-element Vector{Any}:\n 1\n 3\n 5\n\nMore \"tightly\" typed vector can returned by using BangBang.jl interface:\n\njulia> collector!! = push!! |> whencombine(append!!) |> wheninit(Vector{Union{}});\n\njulia> foldxt(collector!!, Filter(isodd), 1:5; basesize = 1)\n3-element Vector{Int64}:\n 1\n 3\n 5\n\nOnline averaging algorithm can be implemented, e.g., by:\n\njulia> averaging = function add_average((sum, count), x)\n (sum + x, count + 1)\n end |> wheninit() do\n (Init(+), 0)\n end |> whencombine() do (sum1, count1), (sum2, count2)\n (sum1 + sum2), (count1 + count2)\n end |> whencomplete() do (sum, count)\n sum / count\n end;\n\njulia> foldl(averaging, Filter(isodd), 1:5)\n3.0\n\njulia> foldxt(averaging, Filter(isodd), 1:50; basesize = 1)\n25.0\n\nAn alternative implementation is to use Map to construct a singleton solution and then merge it into the accumulated solution:\n\njulia> averaging2 = function merge_average((sum1, count1), (sum2, count2))\n (sum1 + sum2, count1 + count2)\n end |> whencomplete() do (sum, count)\n sum / count\n end |> Map() do x\n (x, 1)\n end'; # `'` here is important;\n\njulia> foldl(averaging2, Filter(isodd), 1:5)\n3.0\n\njulia> foldxt(averaging2, Filter(isodd), 1:50; basesize = 1)\n25.0\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.whenstart","page":"Manual","title":"Transducers.whenstart","text":"See wheninit\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.whencomplete","page":"Manual","title":"Transducers.whencomplete","text":"See wheninit\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.whencombine","page":"Manual","title":"Transducers.whencombine","text":"See wheninit\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Early-termination","page":"Manual","title":"Early termination","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"Reduced\nreduced\nunreduced\nifunreduced","category":"page"},{"location":"reference/manual/#Transducers.Reduced","page":"Manual","title":"Transducers.Reduced","text":"Reduced\n\nThe type signaling transducible processes to abort.\n\nnote: Note\nCall reduced function for aborting the transducible process since reduced makes sure x is not doubly wrapped. Reduced is meant to be used as x isa Reduced for checking if the result from transduce is due to early termination.\n\nSee reduced, unreduced.\n\nExamples\n\njulia> using Transducers\n\njulia> function step_demo(y, x)\n if x > 5\n return reduced(y)\n else\n return y + x\n end\n end;\n\njulia> result = transduce(Map(identity), Completing(step_demo), 0, 1:10)\nReduced(15)\n\njulia> result isa Reduced\ntrue\n\njulia> unreduced(result)\n15\n\njulia> result = transduce(Map(identity), Completing(step_demo), 0, 1:4)\n10\n\njulia> result isa Reduced\nfalse\n\njulia> unreduced(result)\n10\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.reduced","page":"Manual","title":"Transducers.reduced","text":"reduced([x = nothing])\n\nStop transducible process with the final value x (default: nothing). Return x as-is if it already is a reduced value.\n\nSee Reduced, unreduced.\n\nThis API is modeled after ensure-reduced in Clojure.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(Enumerate(), \"abcdef\"; init=0) do y, (i, x)\n if x == 'd'\n return reduced(y)\n end\n return y + i\n end\n6\n\njulia> foreach(Enumerate(), \"abc\") do (i, x)\n println(i, ' ', x)\n if x == 'b'\n return reduced()\n end\n end;\n1 a\n2 b\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.unreduced","page":"Manual","title":"Transducers.unreduced","text":"unreduced(x)\n\nUnwrap x if it is a Reduced; do nothing otherwise.\n\nSee Reduced, reduced.\n\nThis API is modeled after unreduced in Clojure.\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.ifunreduced","page":"Manual","title":"Transducers.ifunreduced","text":"ifunreduced(f, [x])\n\nEquivalent to unreduced(x) if x is a Reduced; otherwise run f(x). Return a curried version if x is not provided.\n\nSee: foreach.\n\nExamples\n\njulia> using Transducers\n\njulia> 1 |> ifunreduced() do x\n println(\"called with x = \", x)\n end\ncalled with x = 1\n\njulia> reduced(1) |> ifunreduced() do x\n println(\"called with x = \", x)\n end\n1\n\nNotice that nothing is printed in the last example.\n\nImplementation\n\nifunreduced(f) = x -> ifunreduced(f, x)\nifunreduced(f, x::Reduced) = unreduced(x)\nifunreduced(f, x) = f(x)\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#man-executor","page":"Manual","title":"Executors","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"SequentialEx\nThreadedEx\nDistributedEx\nPreferParallel","category":"page"},{"location":"reference/manual/#Transducers.SequentialEx","page":"Manual","title":"Transducers.SequentialEx","text":"SequentialEx(; simd)\n\nSequential fold executor. It can be passed to APIs from packages such as Folds.jl and FLoops.jl to run the algorithm sequentially.\n\nSee also: foldxl, ThreadedEx and DistributedEx.\n\nKeyword Arguments\n\nsimd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.\n\nExamples\n\njulia> using Folds\n\njulia> Folds.sum(1:3, SequentialEx())\n6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.ThreadedEx","page":"Manual","title":"Transducers.ThreadedEx","text":"ThreadedEx(; basesize, stoppable, nestlevel, simd)\n\nMulti-threaded fold executor. This is the default [1] parallel executor used by Folds.jl and FLoops.jl.\n\nSee also: foldxt, SequentialEx and DistributedEx.\n\n[1]: More specifically, Folds.jl and FLoops.jl uses PreferParallel which in turn defaults to ThreadedEx.\n\nKeyword Arguments\n\nbasesize::Integer = amount(reducible) ÷ nthreads(): A size of chunk in reducible that is processed by each worker. A smaller size may be required when:\ncomputation time for processing each item fluctuates a lot\ncomputation can be terminated by reduced or transducers using it, such as ReduceIf\nstoppable::Bool: [This option usually does not have to be set manually.] The threaded fold executed in the \"stoppable\" mode used for optimizing reduction with reduced has a slight overhead if reduced is not used. This mode can be disabled by passing stoppable = false. It is usually automatically detected and set appropriately. Note that this option is purely for optimization and does not affect the result value.\nnestlevel::Union{Integer,Val}: Specify how many inner Cat (flatten) transducers to be multi-threaded (using TCat). It must be a positive integer, Val of positive integer, or Val(:inf). Val(:inf) means to use multi-threading for all Cat transducers. Note that Cat transducer should be statically known. That is to say, the fold implementation sees two Cats in ... |> Map(f) |> Cat() |> Cat() but only one Cat in ... |> Map(x -> f(x) |> Cat()) |> Cat() even though they are semantically identical.\nsimd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.\n\nExamples\n\njulia> using Folds\n\njulia> Folds.sum(1:3, ThreadedEx(basesize = 1))\n6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.DistributedEx","page":"Manual","title":"Transducers.DistributedEx","text":"DistributedEx(; pool, basesize, threads_basesize, simd)\n\nDistributed fold executor. It can be passed to APIs from packages such as Folds.jl and FLoops.jl to run the algorithm sequentially.\n\nSee also: foldxd, SequentialEx and ThreadedEx.\n\nKeyword Arguments\n\npool::AbstractWorkerPool: Passed to Distributed.remotecall.\nbasesize::Integer = amount(array) ÷ nworkers(): A size of chunk in array that is processed by each worker. A smaller size may be required when computation time for processing each item can fluctuate a lot.\nthreads_basesize::Integer = basesize ÷ nthreads(): A size of chunk in array that is processed by each task in each worker process. The default setting assumes that the number of threads used in all workers are the same. For heterogeneous setup where each worker process has different number of threads, it may be required to use smaller threads_basesize and basesize to get a good performance.\nsimd: If true or :ivdep, enable SIMD using Base.@simd. If :ivdep, use @simd ivdep for ... end variant. Read Julia manual of Base.@simd to understand when it is appropriate to use this option. For example, simd = :ivdep must not be used with stateful transducer like Scan. If false (default), Base.@simd is not used.\n\nExamples\n\njulia> using Folds\n\njulia> Folds.sum(1:3, DistributedEx())\n6\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.PreferParallel","page":"Manual","title":"Transducers.PreferParallel","text":"PreferParallel(; simd, basesize)\n\nA \"placeholder\" executor that indicates preference to parallel execution.\n\nThis lets the input data collection decide preferred execution strategy (e.g., CUDAEx for CuArray when FoldsCUDA.jl is available), assuming that the reducing function is associative. The default executor is ThreadedEx. As an optional feature, some input data collections support (e.g., AbstractChannel) automatically demoting the execution strategy to SequentialEx. An error is thrown if the automatic detection fails,\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Miscellaneous","page":"Manual","title":"Miscellaneous","text":"","category":"section"},{"location":"reference/manual/","page":"Manual","title":"Manual","text":"SplitBy\nTransducer(::Transducers.Comprehension)\nreducingfunction\nCompleting\nInit\nOnInit\nCopyInit\nright\nsetinput\nAdHocFoldable\nwithprogress\nBase.mapfoldl\nBase.mapreduce","category":"page"},{"location":"reference/manual/#Transducers.SplitBy","page":"Manual","title":"Transducers.SplitBy","text":"SplitBy(f; [keepend = false,] [keepempty = false,])\n\nSplit input collection into chunks delimited by the elements on which f returns true. This can be used to implement parallel and lazy versions of functions like eachline and split.\n\nIf keepend is true (or Val(true)), include the \"delimiter\"/end element at the end of each chunk. If keepempty is true (or Val(true)), include empty chunks. When keepend is true, the value of keepempty is irrelevant since the chunks cannot be empty (i.e., it at least contains the end).\n\nThe input collection (xs in SplitBy(...)(xs)) has to support eachindex and view or SubString.\n\nExtended Help\n\nExamples\n\nFor demonstration, consider the following input stream and SplitBy(iszero; ...) used with the following options:\n\ninput keepend=false keepend=false keepend=true\n keepempty=false keepempty=true\n\n1 `. `. `.\n2 | y1 | y1 | y1\n3 ,' ,' |\n0 ,'\n1 `. `. `.\n2 | y2 | y2 | y2\n3 | | |\n4 ,' ,' |\n0 __ y3 ,'\n0 ] y3\n1 `. `. `.\n2 | y3 | y4 | y4\n\nIn the above diagram, yi (i = 1, 2, 3, 4) are the output of SplitBy. This can be checked in the REPL easily as follows. (Note: we are using Map(collect) for cleaner printing; it's not required unless the arrays is mutated in the downstream.)\n\njulia> using Transducers\n\njulia> xs = [1, 2, 3, 0, 1, 2, 3, 4, 0, 0, 1, 2]; # input\n\njulia> xs |> SplitBy(iszero) |> Map(collect) |> collect\n3-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [1, 2, 3, 4]\n [1, 2]\n\njulia> xs |> SplitBy(iszero; keepempty = true) |> Map(collect) |> collect\n4-element Vector{Vector{Int64}}:\n [1, 2, 3]\n [1, 2, 3, 4]\n []\n [1, 2]\n\njulia> xs |> SplitBy(iszero; keepend = true) |> Map(collect) |> collect\n4-element Vector{Vector{Int64}}:\n [1, 2, 3, 0]\n [1, 2, 3, 4, 0]\n [0]\n [1, 2]\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Transducer-Tuple{Union{Base.Generator, Base.Iterators.Filter, Base.Iterators.Flatten}}","page":"Manual","title":"Transducers.Transducer","text":"Transducer(iterator::Iterators.Generator)\nTransducer(iterator::Iterators.Filter)\nTransducer(iterator::Iterators.Flatten)\n\nExtract \"processing\" part of an iterator as a Transducer. The \"data source\" iterator (i.e., xs in (f(x) for x in xs)) is ignored and nothing must be used as a place holder (i.e., (f(x) for x in nothing)).\n\nSee also eduction.\n\ncompat: Transducers.jl 0.3\nNew in version 0.3.\n\nExamples\n\njulia> using Transducers\n\njulia> xf1 = Transducer(2x for x in nothing if x % 2 == 0);\n\njulia> xf2 = opcompose(Filter(x -> x % 2 == 0), Map(x -> 2x)); # equivalent\n\njulia> xs = 1:10\n collect(xf1, xs) == collect(xf2, xs)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"reference/manual/#Transducers.reducingfunction","page":"Manual","title":"Transducers.reducingfunction","text":"reducingfunction(xf, step; simd)\nxf'(step; simd)\n\nApply transducer xf to the reducing function step to create a new reducing function.\n\ncompat: Transducers.jl 0.3\nNew in version 0.3.\n\nwarning: Warning\nBe careful using reducingfunction with stateful transducers like Scan with mutable init (e.g., Scan(push!, [])). See more in Examples below.\n\nArguments\n\nxf::Transducer: A transducer.\nstep: A callable which accepts 1 and 2 arguments. If it only accepts 2 arguments, wrap it with Completing to \"add\" 1-argument form (i.e., complete protocol).\n\nKeyword Arguments\n\nsimd: false, true, or :ivdep. See maybe_usesimd.\n\nExamples\n\njulia> using Transducers\n\njulia> rf = reducingfunction(Map(x -> x + 1), *);\n\njulia> rf(10, 2) === 10 * (2 + 1)\ntrue\n\nWarning: Be careful when using reducingfunction with stateful transducers\n\nStateful Transducers themselves in Transducers.jl are not inherently broken with reducingfunction. However, it can produce incorrect results when combined with mutable states:\n\njulia> scan_state = [];\n\njulia> rf_bad = opcompose(Scan(push!, scan_state), Cat())'(string);\n\njulia> transduce(rf_bad, \"\", 1:3)\n\"112123\"\n\nThe first run works. However, observe that the vector scan_state is not empty anymore:\n\njulia> scan_state\n3-element Vector{Any}:\n 1\n 2\n 3\n\nThus, the second run produces an incorrect result:\n\njulia> transduce(rf_bad, \"\", 1:3)\n\"123112312123123\"\n\nOne way to solve this issue is to use CopyInit or OnInit.\n\njulia> scan_state = CopyInit([])\nCopyInit(Any[])\n\njulia> rf_good = opcompose(Scan(push!, scan_state), Cat())'(string);\n\njulia> transduce(rf_good, \"\", 1:3)\n\"112123\"\n\njulia> scan_state\nCopyInit(Any[])\n\njulia> transduce(rf_good, \"\", 1:3)\n\"112123\"\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.Completing","page":"Manual","title":"Transducers.Completing","text":"Completing(function)\n\nWrap a function to add a no-op complete protocol. Use it when passing a function without unary method to transduce etc.\n\nThis API is modeled after completing in Clojure.\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.Init","page":"Manual","title":"Transducers.Init","text":"Init\nInit(op) :: InitialValues.InitialValue\n\nThe canonical initializer; i.e., a singleton placeholder usable for init argument of foldl for binary functions with known initial values.\n\nWhen init = Init is passed to foldl etc., Init(op) is called for the bottom reducing function op during the start phase. Init(op) returns InitialValue(op) which acts as the canonical initial value of op.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(+, 1:3 |> Filter(isodd); init = Init)\n4\n\njulia> foldl(+, 2:2:4 |> Filter(isodd); init = Init)\nInitialValue(+)\n\nExtended help\n\nNote that op passed to foldl etc. must be known to InitialValues.jl:\n\njulia> unknown_op(a, b) = a + b;\n\njulia> foldl(unknown_op, 2:2:4 |> Filter(isodd); init = Init)\nERROR: IdentityNotDefinedError: `init = Init` is specified but the identity element `InitialValue(op)` is not defined for\n op = unknown_op\n[...]\n\nInitialValues.asmonoid can be used to wrap a binary function to add (\"adjoin\") the identity value to its domain:\n\njulia> using InitialValues: asmonoid\n\njulia> foldl(asmonoid(unknown_op), 2:2:4 |> Filter(isodd); init = Init)\nInitialValue(::InitialValues.AdjoinIdentity{typeof(unknown_op)})\n\nWhen start(rf, Init) is called with a composite reducing function rf, Init(rf₀) is called for the bottom reducing function rf₀ of rf:\n\njulia> rf = Take(3)'(+); # `+` is the bottom reducing function;\n\njulia> acc = Transducers.start(rf, Init);\n\njulia> Transducers.unwrap(rf, acc)\n(3, InitialValue(+))\n\n\n\n\n\n","category":"constant"},{"location":"reference/manual/#Transducers.OnInit","page":"Manual","title":"Transducers.OnInit","text":"OnInit(f)\n\nCall a callable f to create an initial value.\n\nSee also CopyInit.\n\nOnInit or CopyInit must be used whenever using in-place reduction with foldxt etc.\n\nExamples\n\njulia> using Transducers\n\njulia> xf1 = Scan(push!, [])\nScan(push!, Any[])\n\njulia> foldl(right, xf1, 1:3)\n3-element Vector{Any}:\n 1\n 2\n 3\n\njulia> xf1\nScan(push!, Any[1, 2, 3])\n\nNotice that the array is stored in xf1 and mutated in-place. As a result, second run of foldl contains the results from the first run:\n\njulia> foldl(right, xf1, 10:11)\n5-element Vector{Any}:\n 1\n 2\n 3\n 10\n 11\n\nThis may not be desired. To avoid this behavior, create an OnInit object which takes a factory function to create a new initial value.\n\njulia> xf2 = Scan(push!, OnInit(() -> []))\nScan(push!, OnInit(##9#10()))\n\njulia> foldl(right, xf2, 1:3)\n3-element Vector{Any}:\n 1\n 2\n 3\n\njulia> foldl(right, xf2, [10.0, 11.0])\n2-element Vector{Any}:\n 10.0\n 11.0\n\nKeyword argument init for transducible processes also accept an OnInit:\n\njulia> foldl(push!, Map(identity), \"abc\"; init=OnInit(() -> []))\n3-element Vector{Any}:\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n\nTo create a copy of a mutable object, CopyInit is easier to use.\n\nHowever, more powerful and generic pattern is to use push!! from BangBang.jl and initialize init with Union{}[] so that it automatically finds the minimal element type.\n\njulia> using BangBang\n\njulia> foldl(push!!, Map(identity), \"abc\"; init=Union{}[])\n3-element Vector{Char}:\n 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)\n 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)\n 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.CopyInit","page":"Manual","title":"Transducers.CopyInit","text":"CopyInit(value)\n\nThis is equivalent to OnInit(() -> deepcopy(value)).\n\ncompat: Transducers.jl 0.3\nNew in version 0.3.\n\nExamples\n\njulia> using Transducers\n\njulia> init = CopyInit([]);\n\njulia> foldl(push!, Map(identity), 1:3; init=init)\n3-element Vector{Any}:\n 1\n 2\n 3\n\njulia> foldl(push!, Map(identity), 1:3; init=init) # `init` can be reused\n3-element Vector{Any}:\n 1\n 2\n 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.right","page":"Manual","title":"Transducers.right","text":"right([l, ]r) -> r\n\nIt is simply defined as\n\nright(l, r) = r\nright(r) = r\n\nThis function is meant to be used as step argument for foldl etc. for extracting the last output of the transducers.\n\ncompat: Transducers.jl 0.3\nInitial value must be manually specified. In 0.2, it was automatically set to nothing.\n\nExamples\n\njulia> using Transducers\n\njulia> foldl(right, Take(5), 1:10)\n5\n\njulia> foldl(right, Drop(5), 1:3; init=0) # using `init` as the default value\n0\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.setinput","page":"Manual","title":"Transducers.setinput","text":"setinput(ed::Eduction, coll)\n\nSet input collection of eduction ed to coll.\n\ncompat: Transducers.jl 0.3\nPreviously, setinput combined with eduction was a recommended way to use transducers in a type stable manner. As of v0.3, all the foldl-like functions and eduction are type stable for many cases. This workaround is no more necessary.\n\nExamples\n\njulia> using Transducers\n\njulia> ed = eduction(Map(x -> 2x), Float64[]);\n\njulia> xs = ones(2, 3);\n\njulia> foldl(+, setinput(ed, xs))\n12.0\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Transducers.AdHocFoldable","page":"Manual","title":"Transducers.AdHocFoldable","text":"AdHocFoldable(foldl, [collection = nothing])\n\nProvide a different way to fold collection without creating a wrapper type.\n\nArguments\n\nfoldl::Function: a function that implements __foldl__.\ncollection: a collection passed to the last argument of foldl.\n\nExamples\n\njulia> using Transducers\n using Transducers: @next, complete\n using ArgCheck\n\njulia> function uppertriangle(A::AbstractMatrix)\n @argcheck !Base.has_offset_axes(A)\n return AdHocFoldable(A) do rf, acc, A\n for j in 1:size(A, 2), i in 1:min(j, size(A, 1))\n acc = @next(rf, acc, @inbounds A[i, j])\n end\n return complete(rf, acc)\n end\n end;\n\njulia> A = reshape(1:6, (3, 2))\n3×2 reshape(::UnitRange{Int64}, 3, 2) with eltype Int64:\n 1 4\n 2 5\n 3 6\n\njulia> collect(Map(identity), uppertriangle(A))\n3-element Vector{Int64}:\n 1\n 4\n 5\n\njulia> function circularwindows(xs::AbstractVector, h::Integer)\n @argcheck !Base.has_offset_axes(xs)\n @argcheck h >= 0\n @argcheck 2 * h + 1 <= length(xs)\n return AdHocFoldable(xs) do rf, acc, xs\n buffer = similar(xs, 2 * h + 1)\n @inbounds for i in 1:h\n buffer[1:h - i + 1] .= @view xs[end - h + i:end]\n buffer[h - i + 2:end] .= @view xs[1:h + i]\n acc = @next(rf, acc, buffer)\n end\n for i in h + 1:length(xs) - h\n acc = @next(rf, acc, @inbounds @view xs[i - h:i + h])\n end\n @inbounds for i in 1:h\n buffer[1:end - i] .= @view xs[end - 2 * h + i:end]\n buffer[end - i + 1:end] .= @view xs[1:i]\n acc = @next(rf, acc, buffer)\n end\n return complete(rf, acc)\n end\n end;\n\njulia> collect(Map(collect), circularwindows(1:9, 2))\n9-element Vector{Vector{Int64}}:\n [8, 9, 1, 2, 3]\n [9, 1, 2, 3, 4]\n [1, 2, 3, 4, 5]\n [2, 3, 4, 5, 6]\n [3, 4, 5, 6, 7]\n [4, 5, 6, 7, 8]\n [5, 6, 7, 8, 9]\n [6, 7, 8, 9, 1]\n [7, 8, 9, 1, 2]\n\njulia> expressions(str::AbstractString; kwargs...) =\n AdHocFoldable(str) do rf, val, str\n pos = 1\n while true\n expr, pos = Meta.parse(str, pos;\n raise = false,\n depwarn = false,\n kwargs...)\n expr === nothing && break\n val = @next(rf, val, expr)\n end\n return complete(rf, val)\n end;\n\njulia> collect(Map(identity), expressions(\"\"\"\n x = 1\n y = 2\n \"\"\"))\n2-element Vector{Expr}:\n :(x = 1)\n :(y = 2)\n\njulia> counting = AdHocFoldable() do rf, acc, _\n i = 0\n while true\n i += 1\n acc = @next(rf, acc, i)\n end\n end;\n\njulia> foreach(counting) do i\n @show i;\n i == 3 && return reduced()\n end;\ni = 1\ni = 2\ni = 3\n\n\n\n\n\n","category":"type"},{"location":"reference/manual/#Transducers.withprogress","page":"Manual","title":"Transducers.withprogress","text":"withprogress(foldable) -> foldable′\n\nWrap a foldable so that progress is shown in logging-based progress meter (e.g., Juno) during foldl, foldxt, foldxd, etc.\n\nFor parallel reduction such as foldxt and foldxd, reasonably small basesize and threads_basesize (for foldxd) must be used to ensure that progress information is updated frequently. However, it may slow down the computation if basesize is too small.\n\nKeyword Arguments\n\ninterval::Real: Minimum interval (in seconds) for how often progress is logged.\n\nExamples\n\njulia> using Transducers\n\njulia> xf = Map() do x\n sleep(0.01)\n x\n end;\n\njulia> foldl(+, xf, withprogress(1:100; interval=1e-3)) # see progress meter\n5050\n\nIn foldl and foldxt, withprogress can be nested. This is not supported in foldxd.\n\njulia> xf = opcompose(\n MapCat() do x\n withprogress(1:x; interval=1e-3) # nested progress\n end,\n Map() do x\n sleep(0.5)\n x\n end,\n );\n\njulia> foldxt(+, xf, withprogress(1:10; interval=1e-3); basesize=1)\n220\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.mapfoldl","page":"Manual","title":"Base.mapfoldl","text":"mapfoldl(xf::Transducer, step, reducible; init, simd)\n\nwarning: Warning\nmapfoldl(::Transducer, rf, itr) is deprecated. Use foldl(rf, ::Transducer, itr) if you do not need to call single-argument rf on complete. Use foldl(whencomplete(rf, rf), ::Transducer, itr) to call the single-argument method of rf on complete.\n\nLike foldl but step is not automatically wrapped by Completing.\n\nExamples\n\njulia> using Transducers\n\njulia> function step_demo(state, input)\n @show state, input\n state + input\n end;\n\njulia> function step_demo(state)\n println(\"Finishing with state = \", state)\n state\n end;\n\njulia> mapfoldl(Filter(isodd), step_demo, 1:4, init=0.0)\n(state, input) = (0.0, 1)\n(state, input) = (1.0, 3)\nFinishing with state = 4.0\n4.0\n\n\n\n\n\n","category":"function"},{"location":"reference/manual/#Base.mapreduce","page":"Manual","title":"Base.mapreduce","text":"mapreduce(xf, step, reducible; init, simd)\n\nwarning: Warning\nmapreduce(::Transducer, rf, itr) is deprecated. Use foldxt(rf, ::Transducer, itr) if you do not need to call single-argument rf on complete. Use foldxt(whencomplete(rf, rf), ::Transducer, itr) to call the single-argument method of rf on complete.\n\nLike foldxt but step is not automatically wrapped by Completing.\n\n\n\n\n\n","category":"function"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"EditURL = \"../../../examples/words.jl\"","category":"page"},{"location":"tutorials/words/#parallel-word-count","page":"Parallel word count","title":"Splitting a string into words and counting them in parallel","text":"","category":"section"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"We start from the parallel algorithm presented in Guy Steele's 2009 ICFP talk (video). It splits a space-separated string into list of strings (words). The repeating theme in the talk was to build \"singleton solutions\" and then merge them together using an associative function. We will follow this guideline and slightly extend the algorithm.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"It is highly recommended to just watch the talk for understanding the algorithm. However, we briefly describe how it works.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"When a certain contiguous region of a string is processed, we either already have seen at least one space or not. These two states are tracked using following two types. If there is no space so far, we only have a chunk of a possibly larger word (see example below):","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"struct Chunk\n s::String\nend","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"If there are one or more spaces, (possibly zero) words that are already determined and left/right \"chunks\" have to be tracked separately:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"struct Segment\n l::String\n A::Vector{String}\n r::String\nend","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Here is an example taken from the talk:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Segment(\"Here\", [\"is\", \"a\"], \"\")\n |\n | Segment(\"lian\", [], \"string\")\n __|_____ _|______\n| | | |\nHere is a sesquipedalian string of words\n |________| |________|\n Chunk(\"sesquipeda\") Segment(\"g\", [\"of\"], \"words\")","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"We then need a way to merge two results which can independently in one of the above two states.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"⊕(x::Chunk, y::Chunk) = Chunk(x.s * y.s)\n⊕(x::Chunk, y::Segment) = Segment(x.s * y.l, y.A, y.r)\n⊕(x::Segment, y::Chunk) = Segment(x.l, x.A, x.r * y.s)\n⊕(x::Segment, y::Segment) =\n Segment(x.l,\n append!(append!(x.A, maybewordv(x.r * y.l)), y.A),\n y.r)\n\nmaybewordv(s::String) = isempty(s) ? String[] : [s]\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Input is a sequence of Chars. Each of them has to be converted into a \"singleton solution\" which can be merged with already aggregated (or another singleton) solution with ⊕:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"segment_or_chunk(c::Char) = c == ' ' ? Segment(\"\", [], \"\") : Chunk(string(c))\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Putting them together, we get:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"function collectwords(s::String)\n g = mapfoldl(segment_or_chunk, ⊕, s; init=Segment(\"\", [], \"\"))\n if g isa Char\n return maybewordv(g.s)\n else\n return append!(append!(maybewordv(g.l), g.A), maybewordv(g.r))\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Let's run a few tests covering some edge cases:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"using Test\n@testset begin\n @test collectwords(\"This is a sample\") == [\"This\", \"is\", \"a\", \"sample\"]\n @test collectwords(\" Here is another sample \") == [\"Here\", \"is\", \"another\", \"sample\"]\n @test collectwords(\"JustOneWord\") == [\"JustOneWord\"]\n @test collectwords(\" \") == []\n @test collectwords(\"\") == []\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/#String-splitting-transducer","page":"Parallel word count","title":"String-splitting transducer","text":"","category":"section"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Let's make it re-usable by packaging it into a transducer.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Rather than accumulating words into a vector, we are going to write a transducer that \"emits\" a word as soon as it is ready. The downstream transducer may choose to record everything or only aggregate, e.g., reduced statistics. To this end, we replace Segment in the original algorithm with","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"struct Vacant\n l::String\n r::String\nend","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"and output the words in the \"middle\" without accumulating it. So, instead of segment_or_chunk, we now have:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"vacant_or_chunk(c::Char) = c == ' ' ? Vacant(\"\", \"\") : Chunk(string(c))\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"The idea is to create a custom transducer WordsXF that is used as in","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"... |> Map(vacant_or_chunk) |> WordsXF() |> Filter(!isnothing) |> ...","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"so that the whole transducer streams non-empty words to the downstream. That is to say, the input stream is first processed by vacant_or_chunk which returns either a Vacant or a Chunk. This is processed by WordsXF() which outputs either a word (a String) or nothing. We are using Filter(!isnothing) in the downstream to simplify the definition of WordsXF.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"We define a function extract(x::Union{Chunk,Vacant}, y::Union{Chunk,Vacant}) -> (output, state). It is something like ⊕ but works with Chunk and Vacant:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"extract(x::Chunk, y::Chunk) = nothing, Chunk(x.s * y.s)\nextract(x::Chunk, y::Vacant) = nothing, Vacant(x.s * y.l, y.r)\nextract(x::Vacant, y::Chunk) = nothing, Vacant(x.l, x.r * y.s)\nextract(x::Vacant, y::Vacant) = maybeword(x.r * y.l), Vacant(x.l, y.r)\n\nmaybeword(s) = isempty(s) ? nothing : s\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Let's wrap this in a Transducer.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"using Transducers\nusing Transducers:\n @next, R_, Transducer, combine, complete, inner, next, start, unwrap, wrap, wrapping","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"First, we declare a transducer type:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"struct WordsXF <: Transducer end\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Since this transducer has to keep \"unfinished\" words as its own private state, we use wrap inside start to prepare the state for it:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Transducers.start(rf::R_{WordsXF}, init) = wrap(rf, Chunk(\"\"), start(inner(rf), init))\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Inside of next (i.e., \"loop body\") we call extract defined above to combine the input x::Union{Chunk,Vacant} into state::Union{Chunk,Vacant}. If extract returns a word, it is passed to the inner reducing function:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"function Transducers.next(rf::R_{WordsXF}, acc, x)\n wrapping(rf, acc) do state, iacc\n word, state = extract(state, x)\n iacc = next(inner(rf), iacc, word)\n return state, iacc\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"At the end of a fold, complete is called. We can process unfinished words at this stage. Note that we need to use combine of the inner reducing function (assuming it is associative) to \"prepend\" a word to the accumulated state of the inner reducing function.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"function Transducers.complete(rf::R_{WordsXF}, acc)\n state, iacc = unwrap(rf, acc)\n if state isa Vacant\n pre = @next(inner(rf), start(inner(rf), Init), maybeword(state.l))\n iacc = combine(inner(rf), pre, iacc) # prepending `state.l`\n iacc = @next(inner(rf), iacc, maybeword(state.r)) # appending `state.r`\n else\n @assert state isa Chunk\n iacc = @next(inner(rf), iacc, maybeword(state.s))\n end\n return complete(inner(rf), iacc)\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"That's all we need for using this transducer with sequential folds. For parallel reduce we need combine. It is more or less identical to next:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"function Transducers.combine(rf::R_{WordsXF}, a, b)\n ua, ira = unwrap(rf, a)\n ub, irb = unwrap(rf, b)\n word, uc = extract(ua, ub)\n ira = @next(inner(rf), ira, word)\n irc = combine(inner(rf), ira, irb)\n return wrap(rf, uc, irc)\nend\nnothing # hide\n\nwordsxf = opcompose(Map(vacant_or_chunk), WordsXF(), Filter(!isnothing))\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Test:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"@testset begin\n @test collect(wordsxf, \"This is a sample\") == [\"This\", \"is\", \"a\", \"sample\"]\n @test collect(wordsxf, \" Here is another sample \") == [\"Here\", \"is\", \"another\", \"sample\"]\n @test collect(wordsxf, \"JustOneWord\") == [\"JustOneWord\"]\n @test collect(wordsxf, \" \") == []\n @test collect(wordsxf, \"\") == []\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/#Word-counting-transducer","page":"Parallel word count","title":"Word-counting transducer","text":"","category":"section"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"We can pipe the resulting words into various transducers.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"using MicroCollections: SingletonDict\n\nprocesscount(word) = SingletonDict(word => 1)\ncountxf = opcompose(wordsxf, Map(processcount))","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Transducer countxf constructs a \"singleton solution\" as a dictionary which then accumulated with the associative reducing step function mergewith!!(+) from BangBang.jl:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"using BangBang: mergewith!!\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Putting the transducer and reducing function together, we get:","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"countwords(s; kwargs...) =\n foldxt(mergewith!!(+), countxf, s; init = CopyInit(Dict{String,Int}()), kwargs...)\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Side note: We use CopyInit to create a fresh initial state for each sub-reduce to avoid overwriting mutable data between threads.","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"Let's run some tests with different basesize (length(s) / basesize corresponds to number of tasks to be used):","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"@testset for basesize in [1, 2, 4]\n @test countwords(\"This is a sample\", basesize=basesize) ==\n Dict(\"This\" => 1, \"is\" => 1, \"a\" => 1, \"sample\" => 1)\n @test countwords(\" Here is another sample \", basesize=basesize) ==\n Dict(\"Here\" => 1, \"is\" => 1, \"another\" => 1, \"sample\" => 1)\n @test countwords(\"JustOneWord\", basesize=basesize) ==\n Dict(\"JustOneWord\" => 1)\n @test countwords(\" \", basesize=basesize) == Dict()\n @test countwords(\"\", basesize=basesize) == Dict()\n @test countwords(\"aaa bb aaa aaa bb bb aaa\", basesize=basesize) ==\n Dict(\"aaa\" => 4, \"bb\" => 3)\n @test countwords(\"あああ いい あああ あああ いい いい あああ\", basesize=basesize) ==\n Dict(\"あああ\" => 4, \"いい\" => 3)\nend\nnothing # hide","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"","category":"page"},{"location":"tutorials/words/","page":"Parallel word count","title":"Parallel word count","text":"This page was generated using Literate.jl.","category":"page"},{"location":"reference/interface/#Transducer-interface","page":"Interface","title":"Transducer interface","text":"","category":"section"},{"location":"reference/interface/#Core-interface-for-transducers","page":"Interface","title":"Core interface for transducers","text":"","category":"section"},{"location":"reference/interface/","page":"Interface","title":"Interface","text":"Transducers.AbstractFilter\nTransducers.R_\nTransducers.inner\nTransducers.xform\nTransducers.start\nTransducers.next\nTransducers.@next\nTransducers.complete\nTransducers.combine","category":"page"},{"location":"reference/interface/#Transducers.AbstractFilter","page":"Interface","title":"Transducers.AbstractFilter","text":"AbstractFilter <: Transducer\n\nThe abstract type for filter-like transducers.\n\n\n\n\n\n","category":"type"},{"location":"reference/interface/#Transducers.R_","page":"Interface","title":"Transducers.R_","text":"Transducers.R_{X}\n\nWhen defining a transducer type X, it is often required to dispatch on type rf::R_{X} (Reducing Function) which bundles the current transducer xform(rf)::X and the inner reducing function inner(rf)::R_.\n\n\n\n\n\n","category":"type"},{"location":"reference/interface/#Transducers.inner","page":"Interface","title":"Transducers.inner","text":"Transducers.inner(rf::R_)\n\nReturn the inner reducing function of rf.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.xform","page":"Interface","title":"Transducers.xform","text":"Transducers.xform(rf::R_{X}) -> xf :: X\n\nReturn the transducer xf associated with rf. Returned transducer xf is \"atomic\"; i.e., it is not a Composition transducer type.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.start","page":"Interface","title":"Transducers.start","text":"Transducers.start(rf::R_{X}, state)\n\nThis is an optional interface for a transducer. Default implementation just calls start of the inner reducing function; i.e.,\n\nstart(rf::Reduction, result) = start(inner(rf), result)\n\nIf the transducer X is stateful, it can \"bundle\" its private state with wrap:\n\nstart(rf::R_{X}, result) = wrap(rf, PRIVATE_STATE, start(inner(rf), result))\n\nwhere PRIVATE_STATE is an initial value for the private state that can be used inside next via wrapping.\n\nSee Take, PartitionBy, etc. for real-world examples.\n\nSide notes: There is no related API in Clojure's Transducers. Transducers.jl uses it to implement stateful transducers using \"pure\" functions. The idea is based on a slightly different approach taken in C++ Transducer library atria.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.next","page":"Interface","title":"Transducers.next","text":"Transducers.next(rf::R_{X}, state, input)\n\nThis is the only required interface. It takes the following form (if start is not defined):\n\nnext(rf::R_{X}, result, input) =\n # code calling next(inner(rf), result, possibly_modified_input)\n\nWhen calling next, it is almost always a better idea to use the macro form @next. See the details in its documentation.\n\nSee Map, Filter, Cat, etc. for real-world examples.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.@next","page":"Interface","title":"Transducers.@next","text":"@next(rf, state, input)\n\nIt is expanded to\n\nresult = next(rf, state, input)\nresult isa Reduced && return result\nresult\n\nThis is usually the best way to call next as checking for Reduced is required to support early termination.\n\nSee also: next, Reduced, @return_if_reduced.\n\n\n\n\n\n","category":"macro"},{"location":"reference/interface/#Transducers.complete","page":"Interface","title":"Transducers.complete","text":"Transducers.complete(rf::R_{X}, state)\n\nThis is an optional interface for a transducer. If transducer X has some internal state, this is the last chance to \"flush\" the result.\n\nSee PartitionBy, etc. for real-world examples.\n\nIf start(rf::R_{X}, state) is defined, complete must unwarp state before returning state to the outer reducing function.\n\ncompat: Transducers.jl 0.3\nIn Transducers.jl 0.2, complete had a fallback implementation to automatically call unwrap when wrap is called in start. Relying on this fallback implementation is now deprecated.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.combine","page":"Interface","title":"Transducers.combine","text":"Transducers.combine(rf::R_{X}, state_left, state_right)\n\nThis is an optional interface for a transducer. If transducer X is stateful (i.e., wrap is used in start), it has to be able to combine the private states to support fold functions that require an associative reducing function such as foldxt. Typical implementation takes the following form:\n\nfunction combine(rf::R_{X}, a, b)\n # ,---- `ua` and `ub` are the private state of the transducer `X`\n # / ,-- `ira` and `irb` are the states of inner reducing functions\n # / /\n ua, ira = unwrap(rf, a)\n ub, irb = unwrap(rf, b)\n irc = combine(inner(rf), ira, irb)\n uc = # somehow combine private states `ua` and `ub`\n return wrap(rf, uc, irc)\nend\n\nSee ScanEmit, etc. for real-world examples.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Helpers-for-stateful-transducers","page":"Interface","title":"Helpers for stateful transducers","text":"","category":"section"},{"location":"reference/interface/","page":"Interface","title":"Interface","text":"Transducers.wrap\nTransducers.unwrap\nTransducers.wrapping","category":"page"},{"location":"reference/interface/#Transducers.wrap","page":"Interface","title":"Transducers.wrap","text":"wrap(rf::R_{X}, state, iresult)\n\nPack private state for reducing function rf (or rather the transducer X) with the result iresult returned from the inner reducing function inner(rf). This packed result is typically passed to the outer reducing function.\n\nThis is intended to be used only in start. Inside next, use wrapping.\n\nnote: Implementation detail\nIf iresult is a Reduced, wrap actually unwraps all internal state iresult recursively. However, this is an implementation detail that should not matter when writing transducers.\n\nConsider a reducing step constructed as\n\nrf = opcompose(xf₁, xf₂, xf₃)'(f)\n\nwhere each xfₙ is a stateful transducer and hence needs a private state stateₙ and this stateₙ is constructed in each start(::R_{typeof(xfₙ)}, result). Then, calling start(rf, result)) is equivalent to\n\nwrap(rf,\n state₁, # private state for xf₁\n wrap(inner(rf),\n state₂, # private state for xf₂\n wrap(inner(inner(rf)),\n state₃, # private state for xf₃\n result)))\n\nor equivalently\n\nresult₃ = result\nresult₂ = wrap(inner(inner(rf)), state₃, result₃)\nresult₁ = wrap(inner(rf), state₂, result₂)\nresult₀ = wrap(rf, state₁, result₁)\n\nThe inner most step function receives the original result as the first argument while transducible processes such as foldl only sees the outer-most \"tree\" result₀ during the reduction.\n\nSee wrapping, unwrap, and start.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.unwrap","page":"Interface","title":"Transducers.unwrap","text":"unwrap(rf, result)\n\nUnwrap wraped result to a private state and inner result. Following identity holds:\n\nunwrap(rf, wrap(rf, state, iresult)) == (state, iresult)\n\nThis is intended to be used only in complete. Inside next, use wrapping.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.wrapping","page":"Interface","title":"Transducers.wrapping","text":"wrapping(f, rf, result)\n\nFunction f must take two argument state and iresult, and return a tuple (state, iresult). This is intended to be used only in next, possibly with a do block.\n\nnext(rf::R_{MyTransducer}, result, input) =\n wrapping(rf, result) do my_state, iresult\n # code calling `next(inner(rf), iresult, possibly_modified_input)`\n return my_state, iresult # possibly modified\n end\n\nSee wrap, unwrap, and next.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Interface-for-reducibles","page":"Interface","title":"Interface for reducibles","text":"","category":"section"},{"location":"reference/interface/","page":"Interface","title":"Interface","text":"Transducers.__foldl__\nTransducers.@return_if_reduced","category":"page"},{"location":"reference/interface/#Transducers.__foldl__","page":"Interface","title":"Transducers.__foldl__","text":"__foldl__(rf, init, reducible::T)\n\nLeft fold a reducible with reducing function rf and initial value init. This is primary an API for overloading when the reducible \"container\" or \"context\" (e.g., I/O stream) of type T can provide a better reduction mechanism than the default iterator-based one.\n\nFor a simple iterable type MyType, a valid implementation is:\n\nfunction __foldl__(rf, val, itr::MyType)\n for x in itr\n val = @next(rf, val, x)\n end\n return complete(rf, val)\nend\n\nalthough in this case default __foldl__ can handle MyType and thus there is no need for defining it. In general, defining __foldl__ is useful only when there is a better way to go over items in reducible than Base.iterate.\n\nSee also: @next.\n\n\n\n\n\n","category":"function"},{"location":"reference/interface/#Transducers.@return_if_reduced","page":"Interface","title":"Transducers.@return_if_reduced","text":"@return_if_reduced expr\n\nIt transforms the given expression to:\n\nval = expr\nval isa Reduced && return val\nval\n\nSee also @next.\n\ncompat: Transducers.jl 0.3\nIn v0.2, the calling convention was @return_if_reduced complete(rf, val) and it was transformed to val isa Reduced && return reduced(complete(rf, unreduced(val))). For the rationale behind the change, see this commit message.\n\nExamples\n\njulia> using Transducers: @return_if_reduced\n\njulia> @macroexpand @return_if_reduced f(x)\nquote\n #158#val = f(x)\n #= ... =#\n begin\n #158#val isa Transducers.Reduced && return #158#val\n #= ... =#\n #158#val\n end\nend\n\n\n\n\n\n","category":"macro"},{"location":"#Transducers-for-Julia","page":"Home","title":"Transducers for Julia","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"DocTestSetup = quote\n using Transducers\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Transducers are transformations of \"sequence\" of input that can be composed very efficiently. The interface used by transducers naturally describes a wide range of processes that is expressible as a succession of steps. Furthermore, transducers can be defined without specifying the details of the input and output (collections, streams, channels, etc.) and therefore achieves a full reusability. Transducers are introduced by Rich Hickey, the creator of the Clojure language. His Strange Loop talk is a great introduction to the idea of transducers.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Transducers.jl is an implementation of the transducers in Julia. Aiming to satisfy high-performance needs of Julia users, Transducers.jl uses a formulation that is pure [pure] and aiding type-stability.","category":"page"},{"location":"#Features","page":"Home","title":"Features","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Sequential, multi-threaded, and distributed computation with a single API –- transducers (see overview of parallel processing).\nSupport various table types including DataFrames.jl, StructArrays.jl, TypedTables.jl, etc. using Tables.jl and BangBang.jl API (see copy, etc.).\nOnlineStats.jl integration.\nRobust typocalypse-free implementation of map, collect, and alike based on mutate-or-widen strategy implemented in BangBang.jl.\nUser interface-agnostic progress bar support based on ProgressLogging.jl that works with threaded and distributed processing (see withprogress).","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"using Pkg\nPkg.add(\"Transducers\")","category":"page"},{"location":"#Examples","page":"Home","title":"Examples","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you are familiar with iterators (see also Base.Iterators and IterTools.jl) it would look very familiar to you:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> using Transducers\n\njulia> 1:3 |> Map(x -> 2x) |> collect # double each element\n3-element Vector{Int64}:\n 2\n 4\n 6\n\njulia> 1:6 |> Filter(iseven) |> collect # collect only evens\n3-element Vector{Int64}:\n 2\n 4\n 6\n\njulia> 1:3 |> MapCat(x -> 1:x) |> collect # concatenate mapped results\n6-element Vector{Int64}:\n 1\n 1\n 2\n 1\n 2\n 3\n","category":"page"},{"location":"","page":"Home","title":"Home","text":"Transducers can be composed:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> 1:6 |> Filter(iseven) |> Map(x -> 2x) |> collect\n3-element Vector{Int64}:\n 4\n 8\n 12","category":"page"},{"location":"","page":"Home","title":"Home","text":"An efficient way to use transducers is combination with foldl. The computation is compiled down to an efficient loop you would write by hand::","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> foldl(+, 1:6 |> Filter(iseven) |> Map(x -> 2x))\n24","category":"page"},{"location":"","page":"Home","title":"Home","text":"For more detailed discussions on the difference to iterators, see Comparison to iterators.","category":"page"},{"location":"#List-of-transducers","page":"Home","title":"List of transducers","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Here is the list of pre-defined transducers:","category":"page"},{"location":"","page":"Home","title":"Home","text":"import Markdown\nimport Transducers\nMarkdown.MD(Transducers.TransducerLister())","category":"page"},{"location":"#Links","page":"Home","title":"Links","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"\"Transducers\" by Rich Hickey - YouTube\nRich Hickey - Inside Transducers - YouTube\nCppCon 2015: Juan Pedro Bolívar Puente “Transducers: from Clojure to C++\" - YouTube","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"[pure]: ...although not pure in the strong sense as Base.@pure.","category":"page"}] +} diff --git a/v0.4.83/siteinfo.js b/v0.4.83/siteinfo.js new file mode 100644 index 00000000..d65ee288 --- /dev/null +++ b/v0.4.83/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "v0.4.83"; diff --git a/v0.4.83/tutorials/tutorial_missings/index.html b/v0.4.83/tutorials/tutorial_missings/index.html new file mode 100644 index 00000000..1a4662e9 --- /dev/null +++ b/v0.4.83/tutorials/tutorial_missings/index.html @@ -0,0 +1,185 @@ + +Tutorial: Missing values · Transducers.jl

Tutorial: missing value handling

This tutorial illustrates the usage of Transducers.jl by stepping through various handling of missing values.

using Transducers

Dot product

Here is a simple way to compute a dot product using MapSplat:

zip(1:3, 10:2:14) |> MapSplat(*) |> sum
76

Let's see what it does step by step. First we create a "printer" transducer using the following function (see Map):

xf_printer(label) = Map() do x
+    println(label, ": ", x)
+    return x  # just return it as-is
+end

This transducer just pass-through the input while printing its value (prefixed by a label). Let's sandwich the previous MapSplat(*) with it:

zip(1:3, 10:2:14) |>
+xf_printer(" input") |>
+MapSplat(*) |>
+xf_printer("output") |>
+sum
 input: (1, 10)
+output: 10
+ input: (2, 12)
+output: 24
+ input: (3, 14)
+output: 42

You can see that the input tuple (1, 10) is splatted into function * by MapSplat which then outputs 10. This is repeated for all inputs.

Perhaps unfortunately, this way of computing a dot product propagates any missing values contained in the input arrays to the result (which may actually be desired in certain cases).

xs = [1, missing, 3, 2]
+ys = [10, 14, missing, 12]
+zip(xs, ys) |> MapSplat(*) |> sum
missing

However, it is very simple to ignore any missing values using OfType:

zip(xs, ys) |> OfType(Tuple{Vararg{Number}}) |> MapSplat(*) |> sum
34

Here, Tuple{Vararg{Number}} is a type that matches with a tuple of any length with numbers. It does not match with a tuple if it has a missing.

@assert (1, 0.5) isa Tuple{Vararg{Number}}
+@assert (1, 0.5, 2im) isa Tuple{Vararg{Number}}
+@assert !((1, missing) isa Tuple{Vararg{Number}})

The part ... |> OfType(Tuple{Vararg{Number}}) |> MapSplat(*) can be factored out using opcompose:

xf_mdot = opcompose(OfType(Tuple{Vararg{Number}}), MapSplat(*));

or equivalently

OfType(Tuple{Vararg{Number}}) ⨟ MapSplat(*)

The transducer xf_mdot can be used where previously OfType(Tuple{Vararg{Number}}) |> MapSplat(*) was used:

zip(xs, ys) |> xf_mdot |> sum
34

Covariance

Transducer xf_mdot above can also be used to compute the covariance. First, we need the number of pairs of elements in xs and ys that both of them are not missing:

nonmissings = zip(xs, ys) |> Map(x -> x isa Tuple{Vararg{Number}}) |> count
2

Finally, we have to pre-process the input to xf_mdot by subtracting the average. It's easy to do this with Map:

using Statistics: mean
+
+function xf_demean(xs, ys)
+    xmean = mean(skipmissing(xs))
+    ymean = mean(skipmissing(ys))
+    return Map(((x, y),) -> (x - xmean, y - ymean))
+end

We can then compute the covariance by combining xf_demean and xf_mdot:

s = zip(xs, ys) |> xf_demean(xs, ys) |> xf_mdot |> sum
+s / nonmissings
1.0

In xf_demean, the averages of the vectors xs and ys are computed separately. It is also easy to compute the averages of the elements where both xs and ys are non-missing:

function xf_demean2(xs, ys)
+    n, xsum, ysum =
+        zip(xs, ys) |>
+        OfType(Tuple{Vararg{Number}}) |>
+        Map(((x, y),) -> (1, x, y)) |>
+        Broadcasting() |>
+        sum
+    xmean = xsum / n
+    ymean = ysum / n
+    return Map(((x, y),) -> (x - xmean, y - ymean))
+end
+
+s = zip(xs, ys) |> xf_demean2(xs, ys) |> xf_mdot |> sum
+s / nonmissings
0.5

In xf_demean2, we used Broadcasting transducer to broadcast elements of the tuple (1, x, y) over the reducing function of sum (i.e., +).

Advanced: TeeRF and ProductRF

Alternatively, it can also be computed using by combining foldxl, ProductRF, TeeRF, and DataTools.inc1 (see below for how TeeRF and ProductRF work):

using DataTools: inc1
+
+function xf_demean3(xs, ys)
+    n, (xsum, ysum) =
+        zip(xs, ys) |>
+        OfType(Tuple{Vararg{Number}}) |>
+        foldxl(TeeRF(inc1, ProductRF(+, +)))
+    xmean = xsum / n
+    ymean = ysum / n
+    return Map(((x, y),) -> (x - xmean, y - ymean))
+end
+
+s = zip(xs, ys) |> xf_demean3(xs, ys) |> xf_mdot |> sum
+s / nonmissings
0.5

Vectorized reduction

reduce, sum, etc. in Base support dims argument. Transducers.jl does not support this argument as of writing. However, this can easily be emulated using eachcol, eachrow, or eachslice iterators in Base.

xs = [
+    0       missing 1       2
+    3       4       5       missing
+    missing 6       7       missing
+]
+
+if VERSION < v"1.1"
+    using Compat: eachcol
+end
+eachcol(xs) |> Broadcasting() |> NotA(Missing) |> sum
3-element Vector{Any}:
+  3
+ 12
+ 13

Here, we use NotA transducer that filters out missing values:

[1, 2, missing, 3] |> NotA(Missing) |> collect
3-element Vector{Int64}:
+ 1
+ 2
+ 3

Above computation returns the sum over each row without taking into account the relationship within a column. Another possibly useful reduction is the sum of the columns with no missing values. This can easily be done by filtering before:

eachcol(xs) |> Filter(x -> !any(ismissing, x)) |> Broadcasting() |> sum
3-element Vector{Int64}:
+ 1
+ 5
+ 7

findmax and findmin

Another useful operation is findmax/findmin. Using Filter, missing values can be filtered out by

filtered_pairs = [1, 3, missing, 0] |> pairs |> Filter(!(ismissing ∘ last))
+collect(filtered_pairs)
3-element Vector{Pair{Int64, Union{Missing, Int64}}}:
+ 1 => 1
+ 2 => 3
+ 4 => 0

These key-value pairs can be accumulated by the following reducing step function:

#                     ,--- current state
+#                     |
+#                     |              ,-- input
+#                     |              |
+function findmax_step((argmax, max), (index, value))
+    argmax, max = value > max ? (index, value) : (argmax, max)
+    return argmax => max
+    #        \
+    #         \__ next state
+end
+
+foldxl(findmax_step, filtered_pairs)
2 => 3

or equivalently

[1, 3, missing, 0] |> pairs |> Filter(!(ismissing ∘ last)) |> foldxl(findmax_step)
2 => 3

foldxl is like foldl but always uses Transducers.jl's extended fold protocol. It also has the unary curried method foldxl(rf) defined as xs -> foldxl(rf, xs). It is handy to use in the piping context as in the latter example.

DataTools.rightif can be used for defining findmax/findmin-like functions on the fly:

using DataTools: rightif
+
+foldxl(rightif(<, last), filtered_pairs)
Pair{Int64, Union{Missing, Int64}}(2, 3)

Side note: why Pair{Int,Union{Missing,Int}}?

The result type just above using rightif is Pair{Int,Union{Missing,Int}}:

typeof(foldxl(rightif(<, last), filtered_pairs))
Pair{Int64, Union{Missing, Int64}}

This is because that's the element type of pairs([1, 3, missing, 0]) and rightif does not re-construct the input Pair like findmax_step:

[1, 3, missing, 0] |> pairs |> first |> typeof
Pair{Int64, Union{Missing, Int64}}

We can avoid this by pre-processing the input with MapSplat(Pair):

foldxl(rightif(<, last), filtered_pairs |> MapSplat(Pair))
2 => 3

findmin

Similarly, we can define findmin with

function findmin_step((argmin, min), (index, value))
+    argmin, min = value < min ? (index, value) : (argmin, min)
+    return argmin => min
+end
+
+foldxl(findmin_step, filtered_pairs)
4 => 0

and

foldxl(rightif(>, last), filtered_pairs)
Pair{Int64, Union{Missing, Int64}}(4, 0)

Extrema (findminmax)

To compute findmax and findmax in a single sweep, we can use TeeRF to "fan out" the input stream to multiple reducing step functions:

foldxl(TeeRF(findmin_step, findmax_step), filtered_pairs)
(4 => 0, 2 => 3)

or equivalently

foldxl(TeeRF(rightif(>, last), rightif(<, last)), filtered_pairs)
(Pair{Int64, Union{Missing, Int64}}(4, 0), Pair{Int64, Union{Missing, Int64}}(2, 3))

In general, multiple folds on a same collection

a₁ = foldxl(rf₁, xs)
+a₂ = foldxl(rf₂, xs)
+...
+aₙ = foldxl(rfₙ, xs)

can be fused into a single fold using TeeRF

a₁, a₂, ..., aₙ = foldxl(TeeRF(rf₁, rf₂, ..., rfₙ), xs)

provided that the input collection xs and the reducing functions rf₁, rf₂, ..., and rfₙ are not stateful.

More fusing by transforming reducing functions

In the above computation, we have a reducing (step) function

rf = TeeRF(rightif(>, last), rightif(<, last));

a transducer

xf = Filter(!(ismissing ∘ last));

and an iterable

xs = pairs([1, 3, missing, 0]);

In Transducers.jl, a transducer acts as iterator transformation xf(xs) as well as reducing function transformation xf'(rf). Thus, the following calls are equivalent:

@assert foldxl(rf, xf, xs) == (4 => 0, 2 => 3)
+@assert foldxl(rf, xf(xs)) == (4 => 0, 2 => 3)
+@assert foldxl(xf'(rf), xs) == (4 => 0, 2 => 3)

By exploiting this equality, we can fuse more computations by moving the transformation on the side of reducing function. For example, we can compute non-missing extrema and count missings at the same time:

[1, 3, missing, 0] |>
+pairs |>
+MapSplat(Pair) |>  # avoid `Pair{Int,Union{Missing, Int}}`
+foldxl(TeeRF(
+    Map(ismissing ∘ last)'(+),  # count number of missings
+    Filter(!(ismissing ∘ last))'(TeeRF(
+        rightif(>, last),  # find non-missing minimum
+        rightif(<, last),  # find non-missing maximum
+    )),
+))
(1, (4 => 0, 2 => 3))

Using ProductRF, we can compute findmax of individual and zipped items at the same time

zip(
+    pairs([1, 3, missing, 0]),  # produces k1 => v1
+    pairs([4, missing, 6, 5]),  # produces k2 => v2
+) |>
+Map() do ((k1, v1), (k2, v2))
+    (k1 => v1, k2 => v2, (k1, k2) => (v1, v2))
+end |>
+foldxl(ProductRF(
+    Filter(!(ismissing ∘ last))'(rightif(<, last)),  # max of k1 => v1
+    Filter(!(ismissing ∘ last))'(rightif(<, last)),  # max of k2 => v2
+    Filter(((_, (v1, v2)),) -> v1 !== missing && v2 !== missing)'(
+        rightif(<, last)  # max (k1, k2) => (v1, v2)
+    ),
+))
(2 => 3, 3 => 6, (1, 1) => (1, 4))

ProductRF is like TeeRF but acts on the input that is already a tuple. That is to say, given a collection of n-tuple xs, multiple folds on a same collection

a₁ = foldxl(rf₁, (x[1] for x in xs))
+a₂ = foldxl(rf₂, (x[2] for x in xs))
+...
+aₙ = foldxl(rfₙ, (x[n] for x in xs))

can be fused into a single fold using ProductRF

a₁, a₂, ..., aₙ = foldxl(ProductRF(rf₁, rf₂, ..., rfₙ), xs)

provided that the input collection xs and the reducing functions rf₁, rf₂, ..., and rfₙ are not stateful.

Early termination

Base's maximum reports the maximum to be missing when it receives a container with a missing:

maximum([1, 2, missing, 3])
missing

We can obtain the same behavior by using isless instead of > in findmax_step′:

function findmax_step′((argmax, max), (index, value))
+    argmax, max = isless(max, value) ? (index, value) : (argmax, max)
+    return argmax => max
+end
+
+foldl(findmax_step′, pairs([1, 2, missing, 3]))
3 => missing

foldl(findmax_step′, ...) does not stop even after it observed missing. We can easily add early termination by using ReduceIf:

[1, 2, missing, 3] |> pairs |> ReduceIf(ismissing ∘ last) |> foldxl(findmax_step′)
3 => missing

Note that ReduceIf(f) is not same as TakeWhile(!f):

[1, 2, missing, 3] |> pairs |> TakeWhile(!(ismissing ∘ last)) |> foldxl(findmax_step′)
2 => 2

That is to say, TakeWhile does not evaluate the inner reducing step function with the item that triggers the early termination. That's why we need ReduceIf here.

findmin with missing and NaN

Unfortunately, we do not have min-compatible "total" ordering in Base. Thus, we need to create a function that special-cases missing and NaN:

function isgreater(x, y)
+    xisnan = x != x
+    xisnan isa Bool || return false  # x is missing
+    yisnan = y != y
+    yisnan isa Bool || return true  # y is missing
+    xisnan && return false
+    yisnan && return true
+    return isless(y, x)
+end
+
+@assert isgreater(2, 1)
+@assert isgreater(1, missing)
+@assert isgreater(NaN, missing)
+@assert isgreater(1, NaN)
+@assert !isgreater(1, 2)
+@assert !isgreater(missing, 1)
+@assert !isgreater(missing, NaN)
+@assert !isgreater(NaN, 1)

Using isgreater instead of <, we can define findmin_step′ like findmax_step′:

function findmin_step′((argmin, min), (index, value))
+    argmin, min = isgreater(min, value) ? (index, value) : (argmin, min)
+    return argmin => min
+end
+
+foldl(findmax_step′, pairs([1, 2, missing, 3]))
3 => missing

Extrema (findminmax) with early termination

As before, we can fuse findmin_step′ and findmax_step′ using TeeRF. This can also be composed with ReduceIf:

[1, 2, 3, 0, 2] |>
+pairs |>
+ReduceIf(ismissing ∘ last) |>
+foldxl(TeeRF(findmin_step′, findmax_step′))
(4 => 0, 3 => 3)
[1, 2, missing, 0, 2] |>
+pairs |>
+ReduceIf(ismissing ∘ last) |>
+foldxl(TeeRF(findmin_step′, findmax_step′))
(3 => missing, 3 => missing)

Ad-hoc imputation

Using Scan, it is straightforward to fill missing items with the last non-missing item (last observation carried forward):

[1, 3, missing, 0, 2, missing, missing] |>
+pairs |>
+MapSplat(Pair) |>
+Scan() do last, (k, v)
+    ismissing(v) ? last : k => v
+end |>
+collect
7-element Vector{Pair{Int64, Int64}}:
+ 1 => 1
+ 2 => 3
+ 2 => 3
+ 4 => 0
+ 5 => 2
+ 5 => 2
+ 5 => 2

rightif can also be used:

[1, 3, missing, 0, 2, missing, missing] |>
+pairs |>
+MapSplat(Pair) |>
+Scan(rightif(!(ismissing ∘ right), last)) |>
+collect

Note that the output still may contain missing if the first item is missing:

[missing, 1, missing] |>
+pairs |>
+MapSplat(Pair) |>
+Scan(rightif(!(ismissing ∘ right), last)) |>
+collect
3-element Vector{Pair{Int64, Union{Missing, Int64}}}:
+ 1 => missing
+ 2 => 1
+ 2 => 1

This can be worked around by specifying init argument for Scan:

[missing, 1, missing] |>
+pairs |>
+MapSplat(Pair) |>
+Scan(rightif(!(ismissing ∘ right), last), 0 => 0) |>
+collect
3-element Vector{Pair{Int64, Int64}}:
+ 0 => 0
+ 2 => 1
+ 2 => 1

This page was generated using Literate.jl.

diff --git a/v0.4.83/tutorials/tutorial_parallel/index.html b/v0.4.83/tutorials/tutorial_parallel/index.html new file mode 100644 index 00000000..98c8f61e --- /dev/null +++ b/v0.4.83/tutorials/tutorial_parallel/index.html @@ -0,0 +1,147 @@ + +Tutorial: Parallelism · Transducers.jl

Parallel processing tutorial

See also: Overview of parallel processing in Transducers.jl

Quick examples

Sequential processing

using Transducers
+
+xs = randn(10_000_000)
+foldl(+, Map(sin), xs)
346.22356705699764

Thread-based parallelism

Just replace foldl with foldxt, to make use of multiple cores:

foldxt(+, Map(sin), xs)
346.22356705699764

(In my laptop (4 core machine) I start seeing some speedup around length(xs) ≥ 100_000 for this transducer and reducing function.)

Process-based parallelism

using Distributed
+#addprocs(4)  # add worker processes
+
+foldxd(+, Map(sin), xs)
346.22356705699764

(Note: there is likely no speedup for light-weight computation and large input data like this, when using foldxd.)

Parallel processing with iterator comprehensions

You can also use parallel processing functions in Transducers.jl such as foldxt, foldxd, tcollect, dcollect, tcopy and dcopy with iterator comprehensions:

foldxt(+, (sin(x) for x in xs if abs(x) < 1); basesize = 500_000)
-1895.5171345635522
foldxt(+, (x * y for x in 1:3, y in 1:3))
36
tcollect(sin(x) for x in xs if abs(x) < 1)
6824898-element Vector{Float64}:
+  0.8252565580389531
+ -0.8300617544717868
+  0.7844822964655624
+ -0.03279724661903634
+ -0.5652961462871117
+  0.6887793785253857
+ -0.7716536093391957
+  0.6487898919899266
+  0.7652939345558171
+  0.08558627635059872
+  ⋮
+  0.2146817304246814
+  0.328242104232756
+ -0.5339099169603772
+  0.3830588696681145
+  0.61734715936978
+  0.24392177051582176
+ -0.44584895972634175
+  0.1631736265575484
+ -0.7620652279182762
using StructArrays: StructVector
+table = StructVector(a = [1, 2, 3], b = [5, 6, 7])
+
+tcopy((A = row.a + 1, B = row.b - 1) for row in table if isodd(row.a))
2-element StructArray(::Vector{Int64}, ::Vector{Int64}) with eltype @NamedTuple{A::Int64, B::Int64}:
+ (A = 2, B = 4)
+ (A = 4, B = 6)

When can I use foldxt and foldxd?

Requirement 1: Associative reducing step function

Parallel reductions such as foldxt and foldxd requires associative reducing step function. Recall that associativity means that the grouping of evaluations of binary operator does not matter:

op = +  # for example
+a, b, c = 1, 2, 3  # for example
+
+@assert op(op(a, b), c) == op(a, op(b, c))

Given this property, computations like a + b + c + d can be done with different "groupings":

  a + b + c + d
+
+= ((a + b) + c) + d                +
+                                  / \
+                                 +   d
+                                / \
+                               +   c           foldl-like grouping
+                              / \
+                             a   b
+
+= (a + b) + (c + d)                +
+                                  / \
+                                 /   \
+                                /     \        reduce-like grouping
+                               +       +
+                              / \     / \
+                             a   b   c   d

Notice that, in the last grouping, computation of c + d does not have to wait for the result of a + b. This is why we need associativity for parallel execution.

Note

Do not confuse associativity with commutativity op(a, b) = op(b, a). For example, matrix multiplication *(::Matrix, ::Matrix) is associative but not commutative in general. However, since foldxt only requires associativity, it is valid to use foldxt(*, xf, matrices).

As reducing function + is associative, it can be used with foldxt (and foldxd):

foldxt(+, Map(identity), 1:10; init = 0, basesize = 1)
55

and the result is the same as the sequential version:

foldl(+, Map(identity), 1:10; init = 0)
55

Note: basesize is for forcing foldxt to avoid falling back to foldl for small length container such as 1:10.

On the other hand, binary function - is not associative. Thus, foldxt cannot be used instead of foldl (they produce different result):

foldxt(-, Map(identity), 1:10; init = 0, basesize = 1)
-5
foldl(+, Map(identity), 1:10; init = 0)
55

Requirement 2: stateless transducers

Parallel reduction only work with stateless transducers Map, Filter, Cat, etc. and you will get an error when using stateful transducers such as Scan with foldxt or foldxd:

foldxt(+, Scan(+), 1:10; basesize = 1)
ERROR: Stateful transducer Scan(+) does not support `combine`

Stateful transducers cannot be used with foldxt because it is impossible to start processing input collection from the middle when the transducers need to know all previous elements (= stateful).

ScanEmit is a stateful transducer but it is assumed that it is used in a context that outputs can be treated as stateless (see: Splitting a string into words and counting them in parallel).

Example: parallel collect

Note

This section explains the implementation ideas of parallel collect. Pre-defined functions such as tcopy and dcopy should cover many use-cases.

Suppose (pretend) there is a compute-heavy transducer:

xf_compute = opcompose(Filter(!ismissing), Map(x -> x^2))

Transducers.jl supports applying this to an input container and then collecting the results into another container. It can be done sequentially (collect, copy, etc.) and in parallel using threads (tcollect, tcopy) or using multiple processes (dcollect, dcopy). For example:

xs = [abs(x) > 1 ? missing : x for x in randn(10_000)]
+y1 = collect(xf_compute, xs)

Doing this in parallel is as easy as using tcollect or dcollect. However, it is easy to do this manually, too:

using BangBang: append!!
+
+singleton_vector(x) = [x]
+y2 = foldxt(append!!, xs |> xf_compute |> Map(singleton_vector))
+@assert y1 == y2

This code illustrates the common pattern in parallel processing:

  1. Put a result from the transducer in a "singleton solution". Here, it is [x].

  2. Then "merge" the (singleton) solution into the existing one. This is done by append!! in the above example.

To illustrate how foldxt(append!!, xs |> ... |> Map(singleton_vector)) works, let's create a reducing function that records the arguments and returned values of append!!:

chan = Channel(Inf)
+
+function append_and_log!!(a, b)

As arguments and output may be mutated later, we use copy to record the snapshots of their values at this moment:

    a0 = copy(a)
+    b0 = copy(b)
+    c = append!!(a, b)
+    put!(chan, (a0, b0) => copy(c))
+    return c
+end

This function can be used instead of append!!. Let's try simpler and shorter example. This is equivalent to collect(1:4):

foldxt(append_and_log!!, Map(singleton_vector), 1:4; basesize = 1, init = Union{}[])
4-element Vector{Int64}:
+ 1
+ 2
+ 3
+ 4

(See below for why we are using init = Union{}[] here.)

Here is the list of arguments and returned value of append!! in this reduction:

records = Pair[]
+while isready(chan)
+    push!(records, take!(chan))
+end
+records
7-element Vector{Pair}:
+ (Union{}[], [1]) => [1]
+ (Union{}[], [3]) => [3]
+ (Union{}[], [2]) => [2]
+ (Union{}[], [4]) => [4]
+       ([1], [2]) => [1, 2]
+       ([3], [4]) => [3, 4]
+ ([1, 2], [3, 4]) => [1, 2, 3, 4]

This recorded inputs and outputs of append!! show that its "call tree" is:

          [1,2,3,4] <------------- append!!([1,2], [3,4]) == [1,2,3,4]
+         /         \
+    [1,2]           [3,4] <------- append!!([3], [4]) == [3, 4]
+   /     \         /     \
+ [1]     [2]     [3]     [4] <---- append!!([], [4]) == [4]
+ / \     / \     / \     / \
+[] [1]  [] [2]  [] [3]  [] [4]

Compare this to the example a + b + c + d above.

Optimization and generic container handling

Above usage of foldxt is not quite efficient as singleton_vector allocates small objects in the heap. Thus, it makes sense to use immutable objects for the singleton solutions so that Julia compiler can eliminate allocation of the intermediate singleton solutions. Here, this can be done by simply using SVectorinstead of singleton_vector:

using StaticArrays: SVector
+
+foldxt(append!!, Map(SVector), 1:4)
4-element StaticArraysCore.SVector{4, Int64} with indices SOneTo(4):
+ 1
+ 2
+ 3
+ 4

However, notice that the return value is a static vector. This is not ideal when the input collection is large. The output collection type can be specified by init. We can simply use init = Union{}[] in this case:

foldxt(append!!, Map(SVector), 1:4; init = Union{}[])
4-element Vector{Int64}:
+ 1
+ 2
+ 3
+ 4

Note that passing Vector to init of foldxt is usually a wrong choice as it would mean that the same object is simultaneously mutated by different threads. However, since Vector{Union{}} cannot have any element (as there is no object of type Union{}), using Union{}[] for init is an exception and it is a good way to indicate that output vector should use the "smallest" eltype required. That is to say, append!! widens the vector "just enough" to fit the resulting elements.

For generic containers (e.g., various table types), use BangBang.Empty as the empty initial value. This is useful for creating a table object such as DataFrame as the result of parallel processing:

using BangBang: Empty
+using DataFrames: DataFrame
+
+foldxt(append!!, Map(x -> SVector((a = x,))), 1:4; init = Empty(DataFrame))
4×1 DataFrame
+ Row │ a
+     │ Int64
+─────┼───────
+   1 │     1
+   2 │     2
+   3 │     3
+   4 │     4

It is slightly more tricky to make this approach work with other table types such as StructArrays and TypedTables. Use tcopy or dcopy to work with generic containers.

Example: ad-hoc histogram

Following example counts number of occurrence of each leading digit in a distribution of random numbers. First, let's create "singleton solutions" using transducers:

xs = 1_000_000 * randn(10_000_000)
+dicts1 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x
+    y = digits(floor(Int, x))[end]
+    Dict(y => 1)
+end

The singleton solutions can be merged using mergewith!(+, a, b). Conveniently, mergewith!(+) is the curried form (args...) -> mergewith!(+, args...):

rf! = mergewith!(+)
+rf!(Dict(:a => 1, :b => 2), Dict(:b => 3, :c => 4))
Dict{Symbol, Int64} with 3 entries:
+  :a => 1
+  :b => 5
+  :c => 4

This is the form of binary function appropriate for foldl and foldxt.

Note that it is OK to use in-place function mergewith! here because the dictionary passed as a is created by Dict(y => 1) and not shared by anyone. When there is no such guarantee, passing init = OnInit(Dict{Int,Int}) is a good option. Note that passing init = Dict{Int,Int}() to foldxt is not correct as multiple tasks would share and try to mutate the same dictionary this way.

Let's try this with parallel foldxt:

counts1 = foldxt(mergewith!(+), dicts1)

Compare the result with foldl:

counts2 = foldl(mergewith!(+), dicts1)
+@assert counts1 == counts2

Hopefully the result is close to the Benford's law - Wikipedia:

let n = sum(values(counts1))
+    sort!(keys(counts1) .=> values(counts1) ./ n)
+end
9-element Vector{Pair{Int64, Float64}}:
+ 1 => 0.3596507236856513
+ 2 => 0.12888261599435438
+ 3 => 0.08648987784089006
+ 4 => 0.08100887290798561
+ 5 => 0.07744176969759273
+ 6 => 0.07343096608786948
+ 7 => 0.06915306223775601
+ 8 => 0.0643175578858021
+ 9 => 0.0596245536620983

Since we are counting only nine elements, it is actually better to use fixed-size container such as a tuple in this case:

dicts2 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x
+    y = digits(floor(Int, x))[end]
+    ntuple(i -> i == y, 9)
+end
+
+counts3 = foldxt(dicts2; init=ntuple(_ -> 0, 9)) do a, b
+    map(+, a, b)
+end
+@assert Dict(zip(1:9, counts3)) == counts1

Note that, as tuples are immutable, it is valid to pass it as init of foldxt.

MicroCollections.jl for efficient singleton solution

When the appropriate "bins" are not known, mergewith!(+)-based strategy is more appropriate. However, it is not ideal to allocate a small container like Dict(y => 1) in the heap for each iteration. MicroCollections.jl provides singleton (and empty) containers that are designed for this usecase. The SingletonDict is "upcast" to the mutable Dict in the first invocation when merged with BangBang.jl functions:

using BangBang: mergewith!!
+using MicroCollections: SingletonDict
+
+acc1 = mergewith!!(+, SingletonDict(:a => 1), SingletonDict(:b => 1))
Dict(:a => 1, :b => 1)

This dictionary is reused in the subsequent iterations:

acc2 = mergewith!!(+, acc1, SingletonDict(:b => 1))
Dict(:a => 1, :b => 2)
acc3 = mergewith!!(+, acc2, SingletonDict(:c => 1))
Dict(:a => 1, :b => 2, :c => 1)

The first result is reused across these iterations (within a single thread).

@assert acc1 === acc2 === acc3

Finally, Dicts from different threads are merged using the same function mergewith!!(+):

acc4 = Dict(:a => 5, :c => 3)  # from different thread
+acc5 = mergewith!!(+, acc3, acc4)
Dict(:a => 6, :b => 2, :c => 4)

Thus, dicts1 can be optimized simply by replacing Dict(y => 1) with SingletonDict(y => 1):

dicts3 = xs |> Map(abs) |> Filter(x -> x > 1) |> Map() do x
+    y = digits(floor(Int, x))[end]
+    SingletonDict(y => 1)
+end
+
+counts4 = foldxt(mergewith!!(+), dicts3)
+@assert counts1 == counts4

Example: early termination

Find the first element that is multiple of three:

foldxt(ReduceIf(x -> x % 3 == 0), 1:10; init = nothing, basesize = 1) do _, x
+    # # Uncomment for demo:
+    # x == 3 ? sleep(0.1) : @show x  # give other tasks a chance to finish first
+    return x
+end
3

This snippet always returns 3, even though the reductions for c = 6 and c = 9 may finish first.


This page was generated using Literate.jl.

diff --git a/v0.4.83/tutorials/words/index.html b/v0.4.83/tutorials/words/index.html new file mode 100644 index 00000000..4e8e0225 --- /dev/null +++ b/v0.4.83/tutorials/words/index.html @@ -0,0 +1,106 @@ + +Parallel word count · Transducers.jl

Splitting a string into words and counting them in parallel

We start from the parallel algorithm presented in Guy Steele's 2009 ICFP talk (video). It splits a space-separated string into list of strings (words). The repeating theme in the talk was to build "singleton solutions" and then merge them together using an associative function. We will follow this guideline and slightly extend the algorithm.

It is highly recommended to just watch the talk for understanding the algorithm. However, we briefly describe how it works.

When a certain contiguous region of a string is processed, we either already have seen at least one space or not. These two states are tracked using following two types. If there is no space so far, we only have a chunk of a possibly larger word (see example below):

struct Chunk
+    s::String
+end

If there are one or more spaces, (possibly zero) words that are already determined and left/right "chunks" have to be tracked separately:

struct Segment
+    l::String
+    A::Vector{String}
+    r::String
+end

Here is an example taken from the talk:

Segment("Here", ["is", "a"], "")
+   |
+   |       Segment("lian", [], "string")
+ __|_____            _|______
+|        |          |        |
+Here is a sesquipedalian string of words
+          |________|          |________|
+   Chunk("sesquipeda")        Segment("g", ["of"], "words")

We then need a way to merge two results which can independently in one of the above two states.

⊕(x::Chunk, y::Chunk) = Chunk(x.s * y.s)
+⊕(x::Chunk, y::Segment) = Segment(x.s * y.l, y.A, y.r)
+⊕(x::Segment, y::Chunk) = Segment(x.l, x.A, x.r * y.s)
+⊕(x::Segment, y::Segment) =
+    Segment(x.l,
+            append!(append!(x.A, maybewordv(x.r * y.l)), y.A),
+            y.r)
+
+maybewordv(s::String) = isempty(s) ? String[] : [s]

Input is a sequence of Chars. Each of them has to be converted into a "singleton solution" which can be merged with already aggregated (or another singleton) solution with :

segment_or_chunk(c::Char) = c == ' ' ? Segment("", [], "") : Chunk(string(c))

Putting them together, we get:

function collectwords(s::String)
+    g = mapfoldl(segment_or_chunk, ⊕, s; init=Segment("", [], ""))
+    if g isa Char
+        return maybewordv(g.s)
+    else
+        return append!(append!(maybewordv(g.l), g.A), maybewordv(g.r))
+    end
+end

Let's run a few tests covering some edge cases:

using Test
+@testset begin
+    @test collectwords("This is a sample") == ["This", "is", "a", "sample"]
+    @test collectwords(" Here is another sample ") == ["Here", "is", "another", "sample"]
+    @test collectwords("JustOneWord") == ["JustOneWord"]
+    @test collectwords(" ") == []
+    @test collectwords("") == []
+end
Test Summary: | Pass  Total  Time
+test set      |    5      5  0.2s

String-splitting transducer

Let's make it re-usable by packaging it into a transducer.

Rather than accumulating words into a vector, we are going to write a transducer that "emits" a word as soon as it is ready. The downstream transducer may choose to record everything or only aggregate, e.g., reduced statistics. To this end, we replace Segment in the original algorithm with

struct Vacant
+    l::String
+    r::String
+end

and output the words in the "middle" without accumulating it. So, instead of segment_or_chunk, we now have:

vacant_or_chunk(c::Char) = c == ' ' ? Vacant("", "") : Chunk(string(c))

The idea is to create a custom transducer WordsXF that is used as in

... |> Map(vacant_or_chunk) |> WordsXF() |> Filter(!isnothing) |> ...

so that the whole transducer streams non-empty words to the downstream. That is to say, the input stream is first processed by vacant_or_chunk which returns either a Vacant or a Chunk. This is processed by WordsXF() which outputs either a word (a String) or nothing. We are using Filter(!isnothing) in the downstream to simplify the definition of WordsXF.

We define a function extract(x::Union{Chunk,Vacant}, y::Union{Chunk,Vacant}) -> (output, state). It is something like but works with Chunk and Vacant:

extract(x::Chunk, y::Chunk) = nothing, Chunk(x.s * y.s)
+extract(x::Chunk, y::Vacant) = nothing, Vacant(x.s * y.l, y.r)
+extract(x::Vacant, y::Chunk) = nothing, Vacant(x.l, x.r * y.s)
+extract(x::Vacant, y::Vacant) = maybeword(x.r * y.l), Vacant(x.l, y.r)
+
+maybeword(s) = isempty(s) ? nothing : s

Let's wrap this in a Transducer.

using Transducers
+using Transducers:
+    @next, R_, Transducer, combine, complete, inner, next, start, unwrap, wrap, wrapping

First, we declare a transducer type:

struct WordsXF <: Transducer end

Since this transducer has to keep "unfinished" words as its own private state, we use wrap inside start to prepare the state for it:

Transducers.start(rf::R_{WordsXF}, init) = wrap(rf, Chunk(""), start(inner(rf), init))

Inside of next (i.e., "loop body") we call extract defined above to combine the input x::Union{Chunk,Vacant} into state::Union{Chunk,Vacant}. If extract returns a word, it is passed to the inner reducing function:

function Transducers.next(rf::R_{WordsXF}, acc, x)
+    wrapping(rf, acc) do state, iacc
+        word, state = extract(state, x)
+        iacc = next(inner(rf), iacc, word)
+        return state, iacc
+    end
+end

At the end of a fold, complete is called. We can process unfinished words at this stage. Note that we need to use combine of the inner reducing function (assuming it is associative) to "prepend" a word to the accumulated state of the inner reducing function.

function Transducers.complete(rf::R_{WordsXF}, acc)
+    state, iacc = unwrap(rf, acc)
+    if state isa Vacant
+        pre = @next(inner(rf), start(inner(rf), Init), maybeword(state.l))
+        iacc = combine(inner(rf), pre, iacc)  # prepending `state.l`
+        iacc = @next(inner(rf), iacc, maybeword(state.r))  # appending `state.r`
+    else
+        @assert state isa Chunk
+        iacc = @next(inner(rf), iacc, maybeword(state.s))
+    end
+    return complete(inner(rf), iacc)
+end

That's all we need for using this transducer with sequential folds. For parallel reduce we need combine. It is more or less identical to next:

function Transducers.combine(rf::R_{WordsXF}, a, b)
+    ua, ira = unwrap(rf, a)
+    ub, irb = unwrap(rf, b)
+    word, uc = extract(ua, ub)
+    ira = @next(inner(rf), ira, word)
+    irc = combine(inner(rf), ira, irb)
+    return wrap(rf, uc, irc)
+end
+
+wordsxf = opcompose(Map(vacant_or_chunk), WordsXF(), Filter(!isnothing))

Test:

@testset begin
+    @test collect(wordsxf, "This is a sample") == ["This", "is", "a", "sample"]
+    @test collect(wordsxf, " Here is another sample ") == ["Here", "is", "another", "sample"]
+    @test collect(wordsxf, "JustOneWord") == ["JustOneWord"]
+    @test collect(wordsxf, " ") == []
+    @test collect(wordsxf, "") == []
+end
Test Summary: | Pass  Total  Time
+test set      |    5      5  0.3s

Word-counting transducer

We can pipe the resulting words into various transducers.

using MicroCollections: SingletonDict
+
+processcount(word) = SingletonDict(word => 1)
+countxf = opcompose(wordsxf, Map(processcount))
Map(vacant_or_chunk) 
+    WordsXF() 
+    Filter(ComposedFunction) 
+    Map(processcount)

Transducer countxf constructs a "singleton solution" as a dictionary which then accumulated with the associative reducing step function mergewith!!(+) from BangBang.jl:

using BangBang: mergewith!!

Putting the transducer and reducing function together, we get:

countwords(s; kwargs...) =
+    foldxt(mergewith!!(+), countxf, s; init = CopyInit(Dict{String,Int}()), kwargs...)

Side note: We use CopyInit to create a fresh initial state for each sub-reduce to avoid overwriting mutable data between threads.

Let's run some tests with different basesize (length(s) / basesize corresponds to number of tasks to be used):

@testset for basesize in [1, 2, 4]
+    @test countwords("This is a sample", basesize=basesize) ==
+        Dict("This" => 1, "is" => 1, "a" => 1, "sample" => 1)
+    @test countwords(" Here is another sample ", basesize=basesize) ==
+        Dict("Here" => 1, "is" => 1, "another" => 1, "sample" => 1)
+    @test countwords("JustOneWord", basesize=basesize) ==
+        Dict("JustOneWord" => 1)
+    @test countwords(" ", basesize=basesize) == Dict()
+    @test countwords("", basesize=basesize) == Dict()
+    @test countwords("aaa bb aaa aaa bb bb aaa", basesize=basesize) ==
+        Dict("aaa" => 4, "bb" => 3)
+    @test countwords("あああ いい あああ あああ いい いい あああ", basesize=basesize) ==
+        Dict("あああ" => 4, "いい" => 3)
+end
Test Summary: | Pass  Total  Time
+basesize = 1  |    7      7  0.5s
+Test Summary: | Pass  Total  Time
+basesize = 2  |    7      7  0.0s
+Test Summary: | Pass  Total  Time
+basesize = 4  |    7      7  0.0s

This page was generated using Literate.jl.

diff --git a/versions.js b/versions.js index 5b19d596..58a131c9 100644 --- a/versions.js +++ b/versions.js @@ -6,5 +6,5 @@ var DOC_VERSIONS = [ "v0.1", "dev", ]; -var DOCUMENTER_NEWEST = "v0.4.82"; +var DOCUMENTER_NEWEST = "v0.4.83"; var DOCUMENTER_STABLE = "stable";