summaryrefslogtreecommitdiff
path: root/doc/neps
diff options
context:
space:
mode:
authorSebastian Berg <sebastian@sipsolutions.net>2020-09-27 13:01:41 -0500
committerGitHub <noreply@github.com>2020-09-27 12:01:41 -0600
commit66685909f174c38ebfbf7f733f40bcf7d9e86d48 (patch)
tree727fd001e9bd6ff60114bbf63843f2111b8734e5 /doc/neps
parent82226d816c67a80ff634fd202c1df32865175232 (diff)
downloadnumpy-66685909f174c38ebfbf7f733f40bcf7d9e86d48.tar.gz
NEP: Edit nep-0042 for more clarity (#17370)
* DOC: Edit NEP-42 for clarity * DOC: Further edits of NEP 42 * DOC: Edit NEP-42 for clarity * DOC: Further edits of NEP 42 * WIP: Work out structure a bit and make intro longer * DOC: Round 3 of NEP 42 edits * Start with a new motivation/overview to be forced upon the rest * restructure along "top-level" categories and rename adjust_descriptors * Small fixups * Small clarity/correctness edits * Use `PyArrayMethod` instead of UFuncImpl I am starting to feel that calling this "array method" (even if it is in no way numpy array specific) is probably the best name. It is not ufunc specific, because ufuncs are dispatching + array method. Calling it ufuncimpl makes sense, but since the UFunc name which would also work perfectly is already taken, maybe a whole new name is better. * DOC: Fold in @seberg revisions * Fix typo * Make first example/overview inherit dtype instead of metaclass it could say `metaclass=DTypeMeta`, but its implicit. * DOC: Add "checklist" to NEP 42 Also anchor NEP 40 figure for reference in NEP 42. * Delete duplicated dtype-discovery section The section must have been duplicated in an merge conflict :/, I scanned through, and I think the version that was in the right place got most edits, although not 100% sure. * DOC: Reorganize scope, standardize heds * DOC: Retitle, revisions up to Casting Also anchor for parametric type discussion in NEP 40 * Some smaller changes/additions * DOC: Reorganize for better flow Also adds a NEP anchor at top. * DOC: Glossary, shuffle "Additional information" bullets * DOC: Small updates for sense and case * Fixup merge (some changes were not saved when finishing merge) * Answer bjnath's questions and motivate user impact It seems most answers bjnath already included himself, this adds a few tweaks. Added a note that tusers will basically have to implement the DType class as outlined is basically what the user will have to implement, so spell that out both at the top and in the C-API to clarify that. * NEP 41: Add subsection on dtype organization with parameters This might go a bit far, but I think the image goes very far in giving people the right idea of how to think of dtypes and DType instances. The question is if we want to even show the "alternative"... * Add bjnath as author * Add new header also to NEP 41 * DOC: Minor: delete horiz rules, tweak 2 headings * Rephrase NEP 41 bullt points in terms of NEP 42 Also changes those for NEP 43, to represent what is done, rather than what is solved (and thus fit better to the way its written for the NEP 42 part) * Try to rewerd paragraphs around setitem/getitem a bit some of these were very confusing, hopefully they are a bit better now. * Make a pass over the array-coercion part * Make careful pass up until array-coercion * Pass over the second half of the NEP 42 draft. * Use "given_descrs" which seems clearer and fix casting I always thought returning the casting safety is an awesome idea, but right now I am actually not so sure it helps much with anything. Its usually simpler, I guess. But if the user requested safe casting and we have an unsafe cast, for example for structured dtypes we will end up doing a lot of work for no reason. If we accept an error return without an error already set this is solved. My original reason was that setting a generic error in the resolve descriptor function would really be pretty annoying, so that returning the casting safety seemed like a good way to avoid worrying about most errors there. The "cast-is-view" output is important though. * Fix copy new intro note to NEP 40 (and fix it in NEP 41) Co-authored-by: Ben Nathanson <github@bigriver.xyz>
Diffstat (limited to 'doc/neps')
-rw-r--r--doc/neps/_static/nep-0041-type-sketch-no-fonts.svg1110
-rw-r--r--doc/neps/_static/nep-0041-type-sketch.svg523
-rw-r--r--doc/neps/nep-0040-legacy-datatype-impl.rst30
-rw-r--r--doc/neps/nep-0041-improved-dtype-support.rst106
-rw-r--r--doc/neps/nep-0042-new-dtypes.rst1928
5 files changed, 2705 insertions, 992 deletions
diff --git a/doc/neps/_static/nep-0041-type-sketch-no-fonts.svg b/doc/neps/_static/nep-0041-type-sketch-no-fonts.svg
new file mode 100644
index 000000000..3250396c5
--- /dev/null
+++ b/doc/neps/_static/nep-0041-type-sketch-no-fonts.svg
@@ -0,0 +1,1110 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"
+ sodipodi:docname="nep-0041-type-sketch-no-fonts.svg"
+ id="svg8"
+ version="1.1"
+ viewBox="0 0 390.05549 139.7222"
+ height="139.7222mm"
+ width="390.05548mm">
+ <defs
+ id="defs2">
+ <rect
+ x="-108.43283"
+ y="116.0488"
+ width="38.824516"
+ height="5.9122801"
+ id="rect3054" />
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker7096"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#00b200;fill-opacity:1;fill-rule:evenodd;stroke:#00b200;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path7094"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker5628"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#000081;fill-opacity:1;fill-rule:evenodd;stroke:#000081;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path5626"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker5618"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Sstart">
+ <path
+ transform="matrix(0.2,0,0,0.2,1.2,0)"
+ style="fill:#000081;fill-opacity:1;fill-rule:evenodd;stroke:#000081;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path5616"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker4826"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#206120;fill-opacity:1;fill-rule:evenodd;stroke:#206120;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4824"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker4400"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4398"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#00b200;fill-opacity:1;fill-rule:evenodd;stroke:#00b200;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker4390"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#b7943d;fill-opacity:1;fill-rule:evenodd;stroke:#b7943d;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4388"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker2037"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#f4ae00;fill-opacity:1;fill-rule:evenodd;stroke:#ffc433;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path2035"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <rect
+ id="rect1296"
+ height="8.8755655"
+ width="16.467854"
+ y="100.87298"
+ x="-2.9674385" />
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow1Lend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lend">
+ <path
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path915"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow1Lstart"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstart">
+ <path
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path912"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ inkscape:guide-bbox="true"
+ showguides="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="27"
+ inkscape:window-x="0"
+ inkscape:window-height="1376"
+ inkscape:window-width="2560"
+ showgrid="false"
+ inkscape:document-rotation="0"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="mm"
+ inkscape:cy="290.82008"
+ inkscape:cx="134.87089"
+ inkscape:zoom="0.98994949"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ lock-margins="true"
+ fit-margin-top="2"
+ fit-margin-left="2"
+ fit-margin-right="2"
+ fit-margin-bottom="2"
+ objecttolerance="29.7"
+ gridtolerance="20.4"
+ guidetolerance="19.1"
+ inkscape:snap-perpendicular="true"
+ inkscape:snap-tangential="true" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ transform="translate(143.44857,-67.864137)">
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1976"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m 175.57699,126.11316 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3044"
+ d="M 172.89254,70.114137 V 205.33633"
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 55.143494,98.892926 H 240.95778 c 1.14406,0 2.06509,0.921034 2.06509,2.065094 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 55.143494 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.065094 2.06509,-2.065094 z"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796609;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="rect5208"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <path
+ d="M -60.569299,98.727824 H 50.002364 c 1.14406,0 2.06509,0.92103 2.06509,2.065086 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H -60.569299 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.144056 0.92103,-2.065086 2.06509,-2.065086 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="rect4618"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <g
+ style="font-size:6.7452px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.505891"
+ id="text4368" />
+ <g
+ style="font-size:3.52778px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1296)"
+ id="text1294" />
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.76111px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text1931"
+ aria-label="Value Storage">
+ <path
+ id="path1309"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 177.73074,82.757808 h 1.46657 l 1.50069,4.176144 1.49689,-4.176144 h 1.46658 l -2.09565,5.65788 h -1.73943 z" />
+ <path
+ id="path1311"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 185.82912,86.505727 q -0.42443,0 -0.64044,0.144005 -0.21222,0.144005 -0.21222,0.424436 0,0.257693 0.17053,0.405487 0.17432,0.144005 0.48128,0.144005 0.38275,0 0.64424,-0.272851 0.26148,-0.276641 0.26148,-0.689708 v -0.155374 z m 2.07292,-0.511597 v 2.421558 h -1.36805 v -0.629075 q -0.27285,0.38654 -0.61392,0.564651 -0.34106,0.174322 -0.82992,0.174322 -0.65939,0 -1.07246,-0.38275 -0.40928,-0.38654 -0.40928,-1.000456 0,-0.746552 0.5116,-1.095195 0.51539,-0.348644 1.61437,-0.348644 h 0.79961 v -0.106109 q 0,-0.322116 -0.25391,-0.469911 -0.2539,-0.151584 -0.79202,-0.151584 -0.43581,0 -0.81098,0.08716 -0.37517,0.08716 -0.69729,0.261483 v -1.034562 q 0.43581,-0.106109 0.8754,-0.159164 0.4396,-0.05684 0.87919,-0.05684 1.14825,0 1.65606,0.454753 0.5116,0.450963 0.5116,1.470366 z" />
+ <path
+ id="path1313"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 189.16397,82.519063 h 1.35668 v 5.896625 h -1.35668 z" />
+ <path
+ id="path1315"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 191.7788,86.76342 v -2.592089 h 1.36426 v 0.424435 q 0,0.344854 -0.004,0.86782 -0.004,0.519176 -0.004,0.693497 0,0.511597 0.0265,0.738973 0.0265,0.223587 0.0909,0.325906 0.0834,0.132636 0.216,0.204639 0.13643,0.072 0.31075,0.072 0.42444,0 0.66697,-0.325906 0.24254,-0.325906 0.24254,-0.905715 v -2.095651 h 1.35667 v 4.244357 h -1.35667 v -0.613916 q -0.30696,0.371381 -0.65182,0.549492 -0.34106,0.174322 -0.75413,0.174322 -0.73518,0 -1.12172,-0.450963 -0.38275,-0.450963 -0.38275,-1.311203 z" />
+ <path
+ id="path1317"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 201.5863,86.28214 v 0.38654 h -3.1719 q 0.0493,0.47749 0.34485,0.716235 0.29559,0.238745 0.82613,0.238745 0.42823,0 0.8754,-0.125057 0.45097,-0.128846 0.92467,-0.386539 v 1.04593 q -0.48128,0.181901 -0.96256,0.272852 -0.48128,0.09474 -0.96256,0.09474 -1.15204,0 -1.79249,-0.583599 -0.63665,-0.587389 -0.63665,-1.644688 0,-1.038352 0.62529,-1.63332 0.62907,-0.594968 1.72806,-0.594968 1.00045,0 1.59921,0.602547 0.60255,0.602548 0.60255,1.610582 z m -1.39458,-0.450963 q 0,-0.386539 -0.22737,-0.621495 -0.22359,-0.238745 -0.58739,-0.238745 -0.39412,0 -0.64045,0.223587 -0.24632,0.219797 -0.30695,0.636653 z" />
+ <path
+ id="path1319"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 209.3133,82.93592 v 1.197515 q -0.46612,-0.208429 -0.9095,-0.314538 -0.44339,-0.106109 -0.83751,-0.106109 -0.52296,0 -0.77308,0.144005 -0.25011,0.144005 -0.25011,0.447174 0,0.227376 0.16674,0.356223 0.17053,0.125057 0.61392,0.216007 l 0.62149,0.125057 q 0.94361,0.18948 1.34152,0.57602 0.39791,0.38654 0.39791,1.098985 0,0.936032 -0.55707,1.394575 -0.55328,0.454752 -1.69395,0.454752 -0.53813,0 -1.08004,-0.102319 -0.54191,-0.10232 -1.08383,-0.303169 v -1.231621 q 0.54192,0.28801 1.04593,0.435804 0.50781,0.144005 0.97772,0.144005 0.47749,0 0.7314,-0.159163 0.2539,-0.159163 0.2539,-0.454752 0,-0.265273 -0.17432,-0.409278 -0.17054,-0.144005 -0.68592,-0.257693 l -0.56465,-0.125057 q -0.84887,-0.181901 -1.24299,-0.579809 -0.39033,-0.397909 -0.39033,-1.072458 0,-0.845082 0.5457,-1.299835 0.5457,-0.454752 1.5689,-0.454752 0.46612,0 0.95877,0.072 0.49265,0.06821 1.0194,0.208429 z" />
+ <path
+ id="path1321"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 212.38667,82.966236 v 1.205095 h 1.39836 v 0.970138 h -1.39836 v 1.800062 q 0,0.29559 0.11748,0.401699 0.11747,0.102319 0.46612,0.102319 h 0.69728 v 0.970139 h -1.1634 q -0.8034,0 -1.14068,-0.333486 -0.33348,-0.337274 -0.33348,-1.140671 v -1.800062 h -0.67455 v -0.970138 h 0.67455 v -1.205095 z" />
+ <path
+ id="path1323"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 216.63482,85.03915 q -0.45097,0 -0.68971,0.325906 -0.23496,0.322116 -0.23496,0.932243 0,0.610126 0.23496,0.936032 0.23874,0.322116 0.68971,0.322116 0.44338,0 0.67834,-0.322116 0.23495,-0.325906 0.23495,-0.936032 0,-0.610127 -0.23495,-0.932243 -0.23496,-0.325906 -0.67834,-0.325906 z m 0,-0.970139 q 1.09519,0 1.70911,0.591179 0.6177,0.591178 0.6177,1.637109 0,1.045931 -0.6177,1.637109 -0.61392,0.591178 -1.70911,0.591178 -1.09899,0 -1.72048,-0.591178 -0.61771,-0.591178 -0.61771,-1.637109 0,-1.045931 0.61771,-1.637109 0.62149,-0.591179 1.72048,-0.591179 z" />
+ <path
+ id="path1325"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 223.09988,85.32716 q -0.17811,-0.08337 -0.35622,-0.121267 -0.17433,-0.04169 -0.35244,-0.04169 -0.52296,0 -0.80718,0.337275 -0.28043,0.333485 -0.28043,0.95877 v 1.955436 h -1.35668 v -4.244357 h 1.35668 v 0.697287 q 0.26148,-0.416857 0.59875,-0.606337 0.34107,-0.19327 0.81477,-0.19327 0.0682,0 0.14779,0.0076 0.0796,0.0038 0.23117,0.02274 z" />
+ <path
+ id="path1327"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 225.67681,86.505727 q -0.42443,0 -0.64044,0.144005 -0.21222,0.144005 -0.21222,0.424436 0,0.257693 0.17053,0.405487 0.17433,0.144005 0.48128,0.144005 0.38275,0 0.64424,-0.272851 0.26148,-0.276641 0.26148,-0.689708 v -0.155374 z m 2.07292,-0.511597 v 2.421558 h -1.36805 v -0.629075 q -0.27285,0.38654 -0.61392,0.564651 -0.34106,0.174322 -0.82992,0.174322 -0.65939,0 -1.07246,-0.38275 -0.40928,-0.38654 -0.40928,-1.000456 0,-0.746552 0.5116,-1.095195 0.51539,-0.348644 1.61437,-0.348644 h 0.79961 v -0.106109 q 0,-0.322116 -0.2539,-0.469911 -0.25391,-0.151584 -0.79203,-0.151584 -0.43581,0 -0.81098,0.08716 -0.37517,0.08716 -0.69728,0.261483 v -1.034562 q 0.4358,-0.106109 0.87539,-0.159164 0.4396,-0.05684 0.87919,-0.05684 1.14825,0 1.65606,0.454753 0.5116,0.450963 0.5116,1.470366 z" />
+ <path
+ id="path1329"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 231.89934,87.695663 q -0.28043,0.371381 -0.6177,0.545703 -0.33728,0.174322 -0.78066,0.174322 -0.77687,0 -1.28468,-0.610127 -0.5078,-0.613916 -0.5078,-1.561317 0,-0.95119 0.5078,-1.557527 0.50781,-0.610126 1.28468,-0.610126 0.44338,0 0.78066,0.174321 0.33727,0.174322 0.6177,0.549493 v -0.629074 h 1.36426 v 3.816131 q 0,1.023193 -0.64802,1.561317 -0.64424,0.541914 -1.87207,0.541914 -0.39791,0 -0.76929,-0.06063 -0.37138,-0.06063 -0.74655,-0.185691 v -1.057299 q 0.35622,0.204638 0.69729,0.303168 0.34106,0.102319 0.68592,0.102319 0.66697,0 0.97771,-0.291799 0.31075,-0.2918 0.31075,-0.913295 z M 231.005,85.054308 q -0.42065,0 -0.65561,0.310748 -0.23495,0.310748 -0.23495,0.879188 0,0.583599 0.22737,0.886768 0.22738,0.299378 0.66319,0.299378 0.42443,0 0.65939,-0.310747 0.23495,-0.310748 0.23495,-0.875399 0,-0.56844 -0.23495,-0.879188 -0.23496,-0.310748 -0.65939,-0.310748 z" />
+ <path
+ id="path1331"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 238.804,86.28214 v 0.38654 h -3.1719 q 0.0493,0.47749 0.34486,0.716235 0.29559,0.238745 0.82613,0.238745 0.42823,0 0.8754,-0.125057 0.45096,-0.128846 0.92466,-0.386539 v 1.04593 q -0.48128,0.181901 -0.96256,0.272852 -0.48128,0.09474 -0.96256,0.09474 -1.15204,0 -1.79248,-0.583599 -0.63665,-0.587389 -0.63665,-1.644688 0,-1.038352 0.62528,-1.63332 0.62908,-0.594968 1.72806,-0.594968 1.00046,0 1.59922,0.602547 0.60254,0.602548 0.60254,1.610582 z m -1.39457,-0.450963 q 0,-0.386539 -0.22738,-0.621495 -0.22358,-0.238745 -0.58739,-0.238745 -0.39412,0 -0.64044,0.223587 -0.24632,0.219797 -0.30696,0.636653 z" />
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.76111px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text1935"
+ aria-label="Parameters and
+Storage options">
+ <path
+ id="path1254"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 78.339383,73.092678 h 2.421558 q 1.080037,0 1.656057,0.481279 0.579809,0.47749 0.579809,1.364258 0,0.890557 -0.579809,1.371837 -0.57602,0.47749 -1.656057,0.47749 h -0.96256 v 1.963015 h -1.458998 z m 1.458998,1.057299 v 1.580265 h 0.807186 q 0.424436,0 0.655601,-0.204638 0.231166,-0.208429 0.231166,-0.587389 0,-0.378961 -0.231166,-0.583599 -0.231165,-0.204639 -0.655601,-0.204639 z" />
+ <path
+ id="path1256"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 85.660899,76.840596 q -0.424436,0 -0.640443,0.144005 -0.212218,0.144005 -0.212218,0.424436 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644233,-0.272852 0.261482,-0.276641 0.261482,-0.689708 V 76.840596 Z M 87.733813,76.329 v 2.421557 h -1.368048 v -0.629074 q -0.272851,0.386539 -0.613915,0.564651 -0.341065,0.174321 -0.829924,0.174321 -0.659391,0 -1.072458,-0.38275 -0.409277,-0.386539 -0.409277,-1.000455 0,-0.746552 0.511596,-1.095196 0.515387,-0.348643 1.614372,-0.348643 h 0.799606 v -0.106109 q 0,-0.322117 -0.253903,-0.469911 -0.253904,-0.151584 -0.792027,-0.151584 -0.435805,0 -0.810976,0.08716 -0.375171,0.08716 -0.697287,0.261483 v -1.034562 q 0.435805,-0.106109 0.875399,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.14825,0 1.656057,0.454752 0.511597,0.450963 0.511597,1.470367 z" />
+ <path
+ id="path1258"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 92.148702,75.662029 q -0.178112,-0.08337 -0.356223,-0.121267 -0.174322,-0.04169 -0.352433,-0.04169 -0.522966,0 -0.807186,0.337275 -0.280431,0.333485 -0.280431,0.95877 v 1.955436 H 88.995751 V 74.5062 h 1.356678 v 0.697287 q 0.261483,-0.416856 0.598758,-0.606336 0.341064,-0.19327 0.814765,-0.19327 0.06821,0 0.147794,0.0076 0.07958,0.0038 0.231166,0.02274 z" />
+ <path
+ id="path1260"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 94.725633,76.840596 q -0.424436,0 -0.640444,0.144005 -0.212217,0.144005 -0.212217,0.424436 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644232,-0.272852 0.261483,-0.276641 0.261483,-0.689708 V 76.840596 Z M 96.798546,76.329 v 2.421557 h -1.368047 v -0.629074 q -0.272852,0.386539 -0.613916,0.564651 -0.341064,0.174321 -0.829923,0.174321 -0.659391,0 -1.072458,-0.38275 -0.409278,-0.386539 -0.409278,-1.000455 0,-0.746552 0.511597,-1.095196 0.515386,-0.348643 1.614371,-0.348643 h 0.799607 v -0.106109 q 0,-0.322117 -0.253904,-0.469911 -0.253903,-0.151584 -0.792027,-0.151584 -0.435804,0 -0.810975,0.08716 -0.375171,0.08716 -0.697287,0.261483 v -1.034562 q 0.435804,-0.106109 0.875398,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.148251,0 1.656058,0.454752 0.511596,0.450963 0.511596,1.470367 z" />
+ <path
+ id="path1262"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 101.99409,75.211066 q 0.2577,-0.394118 0.61013,-0.598757 0.35622,-0.208428 0.78066,-0.208428 0.73139,0 1.11414,0.450963 0.38275,0.450963 0.38275,1.311203 v 2.58451 h -1.36426 v -2.213129 q 0.004,-0.04927 0.004,-0.102319 0.004,-0.05306 0.004,-0.151585 0,-0.450962 -0.13263,-0.651811 -0.13264,-0.204639 -0.42823,-0.204639 -0.38654,0 -0.59876,0.318327 -0.20842,0.318326 -0.216,0.920874 v 2.084282 h -1.36426 v -2.213129 q 0,-0.704866 -0.12127,-0.905715 -0.12126,-0.204639 -0.43201,-0.204639 -0.390332,0 -0.602549,0.322116 -0.212218,0.318327 -0.212218,0.913295 v 2.088072 H 98.052905 V 74.5062 h 1.364258 v 0.621495 q 0.250114,-0.360012 0.57223,-0.541913 0.325907,-0.181901 0.716237,-0.181901 0.43959,0 0.77687,0.212218 0.33727,0.212217 0.51159,0.594967 z" />
+ <path
+ id="path1264"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 110.38428,76.61701 v 0.386539 h -3.1719 q 0.0493,0.47749 0.34485,0.716236 0.29559,0.238745 0.82614,0.238745 0.42822,0 0.8754,-0.125057 0.45096,-0.128847 0.92466,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272851 -0.48128,0.09474 -0.96256,0.09474 -1.15204,0 -1.79248,-0.583599 -0.63666,-0.587388 -0.63666,-1.644688 0,-1.038352 0.62529,-1.633319 0.62907,-0.594968 1.72806,-0.594968 1.00045,0 1.59921,0.602547 0.60255,0.602547 0.60255,1.610582 z m -1.39458,-0.450963 q 0,-0.38654 -0.22737,-0.621495 -0.22359,-0.238745 -0.58739,-0.238745 -0.39412,0 -0.64044,0.223586 -0.24633,0.219797 -0.30696,0.636654 z" />
+ <path
+ id="path1266"
+ style="fill:#000000;stroke-width:0.105503"
+ d="M 112.893,73.301106 V 74.5062 h 1.39836 v 0.970139 H 112.893 v 1.800062 q 0,0.295589 0.11747,0.401698 0.11748,0.102319 0.46613,0.102319 h 0.69728 v 0.970139 h -1.16341 q -0.80339,0 -1.14067,-0.333485 -0.33348,-0.337275 -0.33348,-1.140671 v -1.800062 h -0.67455 V 74.5062 h 0.67455 v -1.205094 z" />
+ <path
+ id="path1268"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 119.35806,76.61701 v 0.386539 h -3.1719 q 0.0493,0.47749 0.34486,0.716236 0.29558,0.238745 0.82613,0.238745 0.42822,0 0.8754,-0.125057 0.45096,-0.128847 0.92466,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272851 -0.48128,0.09474 -0.96256,0.09474 -1.15204,0 -1.79248,-0.583599 -0.63665,-0.587388 -0.63665,-1.644688 0,-1.038352 0.62528,-1.633319 0.62908,-0.594968 1.72806,-0.594968 1.00046,0 1.59921,0.602547 0.60255,0.602547 0.60255,1.610582 z m -1.39457,-0.450963 q 0,-0.38654 -0.22738,-0.621495 -0.22359,-0.238745 -0.58739,-0.238745 -0.39412,0 -0.64044,0.223586 -0.24633,0.219797 -0.30696,0.636654 z" />
+ <path
+ id="path1270"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 123.53799,75.662029 q -0.17811,-0.08337 -0.35622,-0.121267 -0.17432,-0.04169 -0.35243,-0.04169 -0.52297,0 -0.80719,0.337275 -0.28043,0.333485 -0.28043,0.95877 v 1.955436 h -1.35668 V 74.5062 h 1.35668 v 0.697287 q 0.26148,-0.416856 0.59876,-0.606336 0.34106,-0.19327 0.81476,-0.19327 0.0682,0 0.1478,0.0076 0.0796,0.0038 0.23116,0.02274 z" />
+ <path
+ id="path1272"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 127.52845,74.638836 v 1.030773 q -0.4358,-0.181901 -0.84129,-0.272852 -0.40549,-0.09095 -0.7655,-0.09095 -0.38654,0 -0.57602,0.09853 -0.18569,0.09474 -0.18569,0.295589 0,0.162953 0.14021,0.250114 0.14401,0.08716 0.5116,0.128847 l 0.23874,0.03411 q 1.04215,0.132636 1.40216,0.435805 0.36001,0.303168 0.36001,0.95119 0,0.67834 -0.50023,1.019404 -0.50023,0.341064 -1.4931,0.341064 -0.42065,0 -0.87161,-0.06821 -0.44717,-0.06442 -0.92087,-0.19706 v -1.030772 q 0.40548,0.197059 0.82992,0.295589 0.42822,0.09853 0.86782,0.09853 0.39791,0 0.59876,-0.109899 0.20084,-0.109898 0.20084,-0.325906 0,-0.181901 -0.14021,-0.269062 -0.13643,-0.09095 -0.54949,-0.140215 l -0.23875,-0.03032 q -0.90571,-0.113688 -1.26952,-0.420646 -0.3638,-0.306958 -0.3638,-0.932243 0,-0.674549 0.46233,-1.000455 0.46234,-0.325906 1.41732,-0.325906 0.37517,0 0.78823,0.05684 0.41307,0.05684 0.89814,0.178111 z" />
+ <path
+ id="path1274"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 133.43644,76.840596 q -0.42443,0 -0.64044,0.144005 -0.21222,0.144005 -0.21222,0.424436 0,0.257693 0.17053,0.405488 0.17432,0.144005 0.48128,0.144005 0.38275,0 0.64424,-0.272852 0.26148,-0.276641 0.26148,-0.689708 V 76.840596 Z M 135.50935,76.329 v 2.421557 h -1.36804 v -0.629074 q -0.27285,0.386539 -0.61392,0.564651 -0.34106,0.174321 -0.82992,0.174321 -0.65939,0 -1.07246,-0.38275 -0.40928,-0.386539 -0.40928,-1.000455 0,-0.746552 0.5116,-1.095196 0.51539,-0.348643 1.61437,-0.348643 h 0.79961 v -0.106109 q 0,-0.322117 -0.25391,-0.469911 -0.2539,-0.151584 -0.79202,-0.151584 -0.43581,0 -0.81098,0.08716 -0.37517,0.08716 -0.69729,0.261483 v -1.034562 q 0.43581,-0.106109 0.8754,-0.159163 0.4396,-0.05684 0.87919,-0.05684 1.14825,0 1.65606,0.454752 0.51159,0.450963 0.51159,1.470367 z" />
+ <path
+ id="path1276"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 141.03839,76.166047 v 2.58451 h -1.36426 v -0.420646 -1.557528 q 0,-0.549492 -0.0265,-0.75792 -0.0227,-0.208429 -0.0834,-0.306958 -0.0796,-0.132637 -0.21601,-0.204639 -0.13642,-0.07579 -0.31074,-0.07579 -0.42444,0 -0.66697,0.329695 -0.24254,0.325906 -0.24254,0.905716 v 2.088072 h -1.35668 V 74.5062 h 1.35668 v 0.621495 q 0.30696,-0.371381 0.65181,-0.545703 0.34486,-0.178111 0.76171,-0.178111 0.73519,0 1.11415,0.450963 0.38275,0.450963 0.38275,1.311203 z" />
+ <path
+ id="path1278"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 145.18421,75.127695 v -2.273763 h 1.36426 v 5.896625 h -1.36426 v -0.613916 q -0.28043,0.375171 -0.6177,0.549493 -0.33728,0.174321 -0.78066,0.174321 -0.78445,0 -1.28847,-0.621495 -0.50401,-0.625284 -0.50401,-1.606792 0,-0.981507 0.50401,-1.603003 0.50402,-0.625284 1.28847,-0.625284 0.43959,0 0.77687,0.178111 0.34106,0.174322 0.62149,0.545703 z m -0.89434,2.747463 q 0.4358,0 0.66318,-0.318326 0.23116,-0.318327 0.23116,-0.924664 0,-0.606337 -0.23116,-0.924663 -0.22738,-0.318327 -0.66318,-0.318327 -0.43202,0 -0.66318,0.318327 -0.22738,0.318326 -0.22738,0.924663 0,0.606337 0.22738,0.924664 0.23116,0.318326 0.66318,0.318326 z" />
+ <path
+ id="path1280"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 82.276782,82.972176 v 1.197515 q -0.466121,-0.208428 -0.909505,-0.314537 -0.443383,-0.106109 -0.837502,-0.106109 -0.522966,0 -0.773079,0.144005 -0.250114,0.144005 -0.250114,0.447173 0,0.227377 0.166742,0.356223 0.170532,0.125057 0.613916,0.216008 l 0.621495,0.125057 q 0.943612,0.18948 1.34152,0.57602 0.397909,0.386539 0.397909,1.098985 0,0.936032 -0.557072,1.394574 -0.553282,0.454753 -1.693953,0.454753 -0.538124,0 -1.080038,-0.10232 -0.541913,-0.102319 -1.083826,-0.303168 v -1.231621 q 0.541913,0.28801 1.04593,0.435804 0.507807,0.144005 0.977718,0.144005 0.47749,0 0.731394,-0.159163 0.253903,-0.159164 0.253903,-0.454753 0,-0.265272 -0.174321,-0.409277 -0.170533,-0.144005 -0.685919,-0.257693 L 79.817329,86.0986 q -0.848871,-0.181901 -1.24299,-0.57981 -0.390329,-0.397908 -0.390329,-1.072458 0,-0.845081 0.545703,-1.299834 0.545703,-0.454752 1.568896,-0.454752 0.466121,0 0.95877,0.072 0.492648,0.06821 1.019403,0.208428 z" />
+ <path
+ id="path1282"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 85.350152,83.002493 v 1.205094 h 1.398364 v 0.970139 h -1.398364 v 1.800062 q 0,0.295589 0.117477,0.401698 0.117478,0.10232 0.466122,0.10232 h 0.697287 v 0.970138 h -1.163409 q -0.803396,0 -1.140671,-0.333485 -0.333485,-0.337275 -0.333485,-1.140671 v -1.800062 h -0.674549 v -0.970139 h 0.674549 v -1.205094 z" />
+ <path
+ id="path1284"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 89.598298,85.075407 q -0.450963,0 -0.689708,0.325906 -0.234955,0.322116 -0.234955,0.932242 0,0.610127 0.234955,0.936033 0.238745,0.322116 0.689708,0.322116 0.443384,0 0.678339,-0.322116 0.234956,-0.325906 0.234956,-0.936033 0,-0.610126 -0.234956,-0.932242 -0.234955,-0.325906 -0.678339,-0.325906 z m 0,-0.970139 q 1.095196,0 1.709112,0.591178 0.617705,0.591179 0.617705,1.637109 0,1.045931 -0.617705,1.637109 -0.613916,0.591179 -1.709112,0.591179 -1.098985,0 -1.72048,-0.591179 -0.617706,-0.591178 -0.617706,-1.637109 0,-1.04593 0.617706,-1.637109 0.621495,-0.591178 1.72048,-0.591178 z" />
+ <path
+ id="path1286"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 96.063363,85.363417 q -0.178111,-0.08337 -0.356223,-0.121268 -0.174322,-0.04169 -0.352433,-0.04169 -0.522965,0 -0.807186,0.337274 -0.28043,0.333486 -0.28043,0.95877 v 1.955436 h -1.356679 v -4.244357 h 1.356679 v 0.697288 q 0.261482,-0.416857 0.598757,-0.606337 0.341064,-0.19327 0.814765,-0.19327 0.06821,0 0.147795,0.0076 0.07958,0.0038 0.231165,0.02274 z" />
+ <path
+ id="path1288"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 98.640295,86.541984 q -0.424436,0 -0.640443,0.144005 -0.212218,0.144005 -0.212218,0.424435 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644233,-0.272852 0.261482,-0.276641 0.261482,-0.689708 v -0.155373 z m 2.072915,-0.511597 v 2.421557 H 99.345161 V 87.82287 q -0.272851,0.38654 -0.613916,0.564651 -0.341064,0.174322 -0.829923,0.174322 -0.659391,0 -1.072458,-0.38275 -0.409277,-0.38654 -0.409277,-1.000456 0,-0.746552 0.511596,-1.095196 0.515387,-0.348643 1.614372,-0.348643 h 0.799606 v -0.106109 q 0,-0.322116 -0.253903,-0.469911 -0.253904,-0.151584 -0.792027,-0.151584 -0.435805,0 -0.810976,0.08716 -0.375171,0.08716 -0.697287,0.261482 v -1.034562 q 0.435804,-0.106108 0.875399,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.14825,0 1.656055,0.454753 0.5116,0.450962 0.5116,1.470366 z" />
+ <path
+ id="path1290"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 104.86282,87.731919 q -0.28043,0.371382 -0.6177,0.545703 -0.33728,0.174322 -0.78066,0.174322 -0.77687,0 -1.28468,-0.610126 -0.5078,-0.613916 -0.5078,-1.561317 0,-0.951191 0.5078,-1.557528 0.50781,-0.610126 1.28468,-0.610126 0.44338,0 0.78066,0.174322 0.33727,0.174322 0.6177,0.549493 v -0.629075 h 1.36426 v 3.816132 q 0,1.023193 -0.64802,1.561317 -0.64423,0.541913 -1.87207,0.541913 -0.3979,0 -0.76928,-0.06063 -0.37139,-0.06063 -0.74656,-0.185691 v -1.0573 q 0.35623,0.204639 0.69729,0.303169 0.34106,0.102319 0.68592,0.102319 0.66697,0 0.97772,-0.291799 0.31074,-0.2918 0.31074,-0.913295 z m -0.89434,-2.641354 q -0.42065,0 -0.6556,0.310748 -0.23496,0.310747 -0.23496,0.879188 0,0.583599 0.22738,0.886767 0.22737,0.299379 0.66318,0.299379 0.42443,0 0.65939,-0.310747 0.23495,-0.310748 0.23495,-0.875399 0,-0.568441 -0.23495,-0.879188 -0.23496,-0.310748 -0.65939,-0.310748 z" />
+ <path
+ id="path1292"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 111.76748,86.318397 v 0.38654 h -3.17189 q 0.0493,0.47749 0.34485,0.716235 0.29559,0.238745 0.82613,0.238745 0.42823,0 0.8754,-0.125057 0.45096,-0.128847 0.92467,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272852 -0.48128,0.09474 -0.96256,0.09474 -1.15204,0 -1.79249,-0.583599 -0.63665,-0.587389 -0.63665,-1.644689 0,-1.038351 0.62528,-1.633319 0.62908,-0.594968 1.72806,-0.594968 1.00046,0 1.59922,0.602547 0.60254,0.602547 0.60254,1.610582 z m -1.39457,-0.450963 q 0,-0.38654 -0.22738,-0.621495 -0.22358,-0.238745 -0.58738,-0.238745 -0.39412,0 -0.64045,0.223586 -0.24632,0.219798 -0.30696,0.636654 z" />
+ <path
+ id="path1294"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 117.51631,85.075407 q -0.45096,0 -0.6897,0.325906 -0.23496,0.322116 -0.23496,0.932242 0,0.610127 0.23496,0.936033 0.23874,0.322116 0.6897,0.322116 0.44339,0 0.67834,-0.322116 0.23496,-0.325906 0.23496,-0.936033 0,-0.610126 -0.23496,-0.932242 -0.23495,-0.325906 -0.67834,-0.325906 z m 0,-0.970139 q 1.0952,0 1.70912,0.591178 0.6177,0.591179 0.6177,1.637109 0,1.045931 -0.6177,1.637109 -0.61392,0.591179 -1.70912,0.591179 -1.09898,0 -1.72048,-0.591179 -0.6177,-0.591178 -0.6177,-1.637109 0,-1.04593 0.6177,-1.637109 0.6215,-0.591178 1.72048,-0.591178 z" />
+ <path
+ id="path1296"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 122.18511,87.838028 v 2.228288 h -1.35668 v -5.858729 h 1.35668 v 0.621495 q 0.28043,-0.371381 0.62149,-0.545703 0.34107,-0.178111 0.78445,-0.178111 0.78445,0 1.28847,0.625285 0.50401,0.621495 0.50401,1.603002 0,0.981508 -0.50401,1.606793 -0.50402,0.621495 -1.28847,0.621495 -0.44338,0 -0.78445,-0.174322 -0.34106,-0.178111 -0.62149,-0.549493 z m 0.90192,-2.747463 q -0.4358,0 -0.67076,0.322116 -0.23116,0.318327 -0.23116,0.920874 0,0.602547 0.23116,0.924664 0.23496,0.318327 0.67076,0.318327 0.43581,0 0.66318,-0.318327 0.23117,-0.318327 0.23117,-0.924664 0,-0.606336 -0.23117,-0.924663 -0.22737,-0.318327 -0.66318,-0.318327 z" />
+ <path
+ id="path1298"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 127.86573,83.002493 v 1.205094 h 1.39836 v 0.970139 h -1.39836 v 1.800062 q 0,0.295589 0.11747,0.401698 0.11748,0.10232 0.46612,0.10232 h 0.69729 v 0.970138 h -1.16341 q -0.80339,0 -1.14067,-0.333485 -0.33348,-0.337275 -0.33348,-1.140671 v -1.800062 h -0.67455 v -0.970139 h 0.67455 v -1.205094 z" />
+ <path
+ id="path1300"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 130.09401,84.207587 h 1.35668 v 4.244357 h -1.35668 z m 0,-1.652267 h 1.35668 v 1.106564 h -1.35668 z" />
+ <path
+ id="path1302"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 134.77417,85.075407 q -0.45096,0 -0.68971,0.325906 -0.23495,0.322116 -0.23495,0.932242 0,0.610127 0.23495,0.936033 0.23875,0.322116 0.68971,0.322116 0.44339,0 0.67834,-0.322116 0.23496,-0.325906 0.23496,-0.936033 0,-0.610126 -0.23496,-0.932242 -0.23495,-0.325906 -0.67834,-0.325906 z m 0,-0.970139 q 1.0952,0 1.70911,0.591178 0.61771,0.591179 0.61771,1.637109 0,1.045931 -0.61771,1.637109 -0.61391,0.591179 -1.70911,0.591179 -1.09898,0 -1.72048,-0.591179 -0.6177,-0.591178 -0.6177,-1.637109 0,-1.04593 0.6177,-1.637109 0.6215,-0.591178 1.72048,-0.591178 z" />
+ <path
+ id="path1304"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 142.35338,85.867434 v 2.58451 h -1.36426 v -0.420646 -1.557527 q 0,-0.549493 -0.0265,-0.757921 -0.0227,-0.208428 -0.0834,-0.306958 -0.0796,-0.132636 -0.21601,-0.204639 -0.13643,-0.07579 -0.31075,-0.07579 -0.42444,0 -0.66697,0.329696 -0.24253,0.325906 -0.24253,0.905715 v 2.088072 h -1.35668 v -4.244357 h 1.35668 v 0.621495 q 0.30695,-0.371381 0.65181,-0.545703 0.34485,-0.178111 0.76171,-0.178111 0.73518,0 1.11414,0.450963 0.38275,0.450963 0.38275,1.311203 z" />
+ <path
+ id="path1306"
+ style="fill:#000000;stroke-width:0.105503"
+ d="m 146.92743,84.340223 v 1.030773 q -0.4358,-0.181901 -0.84129,-0.272852 -0.40549,-0.09095 -0.7655,-0.09095 -0.38654,0 -0.57602,0.09853 -0.18569,0.09474 -0.18569,0.295589 0,0.162953 0.14022,0.250114 0.144,0.08716 0.51159,0.128846 l 0.23875,0.03411 q 1.04214,0.132636 1.40215,0.435804 0.36001,0.303168 0.36001,0.951191 0,0.678339 -0.50022,1.019403 -0.50023,0.341065 -1.49311,0.341065 -0.42065,0 -0.87161,-0.06821 -0.44717,-0.06442 -0.92087,-0.19706 v -1.030772 q 0.40549,0.197059 0.82992,0.295589 0.42823,0.09853 0.86782,0.09853 0.39791,0 0.59876,-0.109899 0.20085,-0.109898 0.20085,-0.325906 0,-0.181901 -0.14022,-0.269062 -0.13642,-0.09095 -0.54949,-0.140215 l -0.23875,-0.03032 q -0.90571,-0.113688 -1.26951,-0.420646 -0.36381,-0.306958 -0.36381,-0.932242 0,-0.67455 0.46234,-1.000456 0.46233,-0.325906 1.41731,-0.325906 0.37517,0 0.78824,0.05684 0.41306,0.05684 0.89813,0.178111 z" />
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text1939"
+ aria-label="Value Space and
+Behaviour">
+ <path
+ id="path1209"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -41.05733,73.092678 h 1.466577 l 1.500683,4.176144 1.496894,-4.176144 h 1.466577 l -2.095652,5.657879 h -1.739428 z" />
+ <path
+ id="path1211"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -32.958945,76.840596 q -0.424436,0 -0.640444,0.144005 -0.212217,0.144005 -0.212217,0.424436 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644232,-0.272852 0.261483,-0.276641 0.261483,-0.689708 V 76.840596 Z M -30.886032,76.329 v 2.421557 h -1.368047 v -0.629074 q -0.272851,0.386539 -0.613916,0.564651 -0.341064,0.174321 -0.829923,0.174321 -0.659391,0 -1.072458,-0.38275 -0.409278,-0.386539 -0.409278,-1.000455 0,-0.746552 0.511597,-1.095196 0.515386,-0.348643 1.614371,-0.348643 h 0.799607 v -0.106109 q 0,-0.322117 -0.253903,-0.469911 -0.253904,-0.151584 -0.792028,-0.151584 -0.435804,0 -0.810975,0.08716 -0.375171,0.08716 -0.697287,0.261483 v -1.034562 q 0.435804,-0.106109 0.875398,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.148251,0 1.656058,0.454752 0.511596,0.450963 0.511596,1.470367 z" />
+ <path
+ id="path1213"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -29.624094,72.853932 h 1.356679 v 5.896625 h -1.356679 z" />
+ <path
+ id="path1215"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="M -27.009267,77.098289 V 74.5062 h 1.364258 v 0.424436 q 0,0.344854 -0.0038,0.867819 -0.0038,0.519176 -0.0038,0.693498 0,0.511596 0.02653,0.738973 0.02653,0.223586 0.09095,0.325906 0.08337,0.132636 0.216008,0.204638 0.136426,0.072 0.310747,0.072 0.424436,0 0.666971,-0.325906 0.242534,-0.325906 0.242534,-0.905716 V 74.5062 h 1.356679 v 4.244357 h -1.356679 v -0.613916 q -0.306958,0.371381 -0.651812,0.549493 -0.341064,0.174321 -0.754131,0.174321 -0.735183,0 -1.121723,-0.450962 -0.38275,-0.450963 -0.38275,-1.311204 z" />
+ <path
+ id="path1217"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -17.201771,76.61701 v 0.386539 h -3.171899 q 0.04927,0.47749 0.344854,0.716236 0.295589,0.238745 0.826134,0.238745 0.428225,0 0.875399,-0.125057 0.450962,-0.128847 0.924663,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272851 -0.481279,0.09474 -0.962559,0.09474 -1.15204,0 -1.792483,-0.583599 -0.636653,-0.587388 -0.636653,-1.644688 0,-1.038352 0.625284,-1.633319 0.629075,-0.594968 1.72806,-0.594968 1.000455,0 1.599213,0.602547 0.602547,0.602547 0.602547,1.610582 z m -1.394574,-0.450963 q 0,-0.38654 -0.227377,-0.621495 -0.223586,-0.238745 -0.587388,-0.238745 -0.394119,0 -0.640443,0.223586 -0.246325,0.219797 -0.306958,0.636654 z" />
+ <path
+ id="path1219"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -9.4747663,73.270789 v 1.197515 q -0.4661213,-0.208428 -0.9095047,-0.314537 -0.443384,-0.106109 -0.837503,-0.106109 -0.522965,0 -0.773079,0.144005 -0.250114,0.144005 -0.250114,0.447173 0,0.227376 0.166742,0.356223 0.170533,0.125057 0.613916,0.216007 l 0.621496,0.125057 q 0.943611,0.189481 1.3415195,0.57602 0.3979084,0.38654 0.3979084,1.098986 0,0.936032 -0.5570718,1.394574 -0.5532821,0.454752 -1.6939531,0.454752 -0.538124,0 -1.080037,-0.102319 -0.541914,-0.102319 -1.083827,-0.303168 v -1.231622 q 0.541913,0.28801 1.045931,0.435805 0.507807,0.144005 0.977718,0.144005 0.47749,0 0.731393,-0.159164 0.253904,-0.159163 0.253904,-0.454752 0,-0.265272 -0.174322,-0.409277 -0.170532,-0.144005 -0.685918,-0.257693 l -0.564652,-0.125057 q -0.848871,-0.181901 -1.24299,-0.57981 -0.390329,-0.397908 -0.390329,-1.072458 0,-0.845082 0.545703,-1.299834 0.545703,-0.454753 1.568896,-0.454753 0.466122,0 0.95877,0.072 0.492649,0.06821 1.0194037,0.208428 z" />
+ <path
+ id="path1221"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -6.5264561,78.136641 v 2.228287 H -7.8831345 V 74.5062 h 1.3566784 v 0.621495 q 0.2804307,-0.371381 0.6214951,-0.545703 0.3410644,-0.178111 0.7844481,-0.178111 0.7844481,0 1.2884655,0.625284 0.5040174,0.621496 0.5040174,1.603003 0,0.981508 -0.5040174,1.606792 -0.5040174,0.621495 -1.2884655,0.621495 -0.4433837,0 -0.7844481,-0.174321 -0.3410644,-0.178112 -0.6214951,-0.549493 z m 0.9019258,-2.747463 q -0.4358045,0 -0.6707599,0.322116 -0.2311659,0.318327 -0.2311659,0.920874 0,0.602547 0.2311659,0.924664 0.2349554,0.318326 0.6707599,0.318326 0.4358046,0 0.6631808,-0.318326 0.2311659,-0.318327 0.2311659,-0.924664 0,-0.606337 -0.2311659,-0.924663 -0.2273762,-0.318327 -0.6631808,-0.318327 z" />
+ <path
+ id="path1223"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -0.425192,76.840596 q -0.4244357,0 -0.6404431,0.144005 -0.2122179,0.144005 -0.2122179,0.424436 0,0.257693 0.1705322,0.405488 0.1743218,0.144005 0.48127976,0.144005 0.38275005,0 0.64423275,-0.272852 0.26148271,-0.276641 0.26148271,-0.689708 V 76.840596 Z M 1.6477216,76.329 v 2.421557 H 0.27967442 v -0.629074 q -0.27285152,0.386539 -0.61391592,0.564651 -0.3410644,0.174321 -0.8299234,0.174321 -0.6593911,0 -1.072458,-0.38275 -0.4092773,-0.386539 -0.4092773,-1.000455 0,-0.746552 0.5115966,-1.095196 0.5153862,-0.348643 1.61437149,-0.348643 h 0.79960653 v -0.106109 q 0,-0.322117 -0.2539035,-0.469911 -0.2539035,-0.151584 -0.79202732,-0.151584 -0.4358045,0 -0.8109753,0.08716 -0.3751709,0.08716 -0.6972873,0.261483 v -1.034562 q 0.4358046,-0.106109 0.8753987,-0.159163 0.43959407,-0.05684 0.87918819,-0.05684 1.14825013,0 1.65605711,0.454752 0.5115966,0.450963 0.5115966,1.470367 z" />
+ <path
+ id="path1225"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 6.3392508,74.638836 v 1.106565 Q 6.0626097,75.55592 5.7821789,75.46497 q -0.2766411,-0.09095 -0.5760198,-0.09095 -0.5684407,0 -0.8867675,0.333486 -0.3145371,0.329695 -0.3145371,0.924663 0,0.594968 0.3145371,0.928453 0.3183268,0.329696 0.8867675,0.329696 0.3183267,0 0.6025471,-0.09474 0.2880099,-0.09474 0.5305446,-0.280431 V 78.6255 q -0.3183268,0.117478 -0.6480224,0.174322 -0.325906,0.06063 -0.6556015,0.06063 -1.1482502,0 -1.7962725,-0.587388 -0.6480224,-0.591178 -0.6480224,-1.640899 0,-1.04972 0.6480224,-1.637109 0.6480223,-0.591178 1.7962725,-0.591178 0.3334852,0 0.6556015,0.06063 0.325906,0.05684 0.6480224,0.174322 z" />
+ <path
+ id="path1227"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 11.747019,76.61701 v 0.386539 H 8.5751198 q 0.049265,0.47749 0.344854,0.716236 0.2955891,0.238745 0.8261337,0.238745 0.4282255,0 0.8753985,-0.125057 0.450963,-0.128847 0.924664,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272851 -0.48128,0.09474 -0.9625594,0.09474 -1.1520398,0 -1.7924829,-0.583599 -0.6366536,-0.587388 -0.6366536,-1.644688 0,-1.038352 0.6252848,-1.633319 0.6290743,-0.594968 1.7280596,-0.594968 1.0004555,0 1.5992135,0.602547 0.602547,0.602547 0.602547,1.610582 z m -1.394575,-0.450963 q 0,-0.38654 -0.227376,-0.621495 -0.2235867,-0.238745 -0.5873887,-0.238745 -0.3941189,0 -0.6404432,0.223586 -0.2463243,0.219797 -0.3069579,0.636654 z" />
+ <path
+ id="path1229"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 17.37837,76.840596 q -0.424436,0 -0.640443,0.144005 -0.212218,0.144005 -0.212218,0.424436 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644233,-0.272852 0.261483,-0.276641 0.261483,-0.689708 V 76.840596 Z M 19.451284,76.329 v 2.421557 h -1.368047 v -0.629074 q -0.272852,0.386539 -0.613916,0.564651 -0.341065,0.174321 -0.829924,0.174321 -0.659391,0 -1.072458,-0.38275 -0.409277,-0.386539 -0.409277,-1.000455 0,-0.746552 0.511597,-1.095196 0.515386,-0.348643 1.614371,-0.348643 h 0.799607 v -0.106109 q 0,-0.322117 -0.253904,-0.469911 -0.253903,-0.151584 -0.792027,-0.151584 -0.435805,0 -0.810976,0.08716 -0.37517,0.08716 -0.697287,0.261483 v -1.034562 q 0.435805,-0.106109 0.875399,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.14825,0 1.656057,0.454752 0.511597,0.450963 0.511597,1.470367 z" />
+ <path
+ id="path1231"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 24.980316,76.166047 v 2.58451 h -1.364258 v -0.420646 -1.557528 q 0,-0.549492 -0.02653,-0.75792 -0.02274,-0.208429 -0.08337,-0.306958 -0.07958,-0.132637 -0.216007,-0.204639 -0.136426,-0.07579 -0.310748,-0.07579 -0.424435,0 -0.66697,0.329695 -0.242535,0.325906 -0.242535,0.905716 v 2.088072 H 20.713221 V 74.5062 h 1.356678 v 0.621495 q 0.306958,-0.371381 0.651812,-0.545703 0.344854,-0.178111 0.761711,-0.178111 0.735183,0 1.114143,0.450963 0.382751,0.450963 0.382751,1.311203 z" />
+ <path
+ id="path1233"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 29.126141,75.127695 v -2.273763 h 1.364258 v 5.896625 h -1.364258 v -0.613916 q -0.28043,0.375171 -0.617705,0.549493 -0.337275,0.174321 -0.780659,0.174321 -0.784448,0 -1.288465,-0.621495 -0.504018,-0.625284 -0.504018,-1.606792 0,-0.981507 0.504018,-1.603003 0.504017,-0.625284 1.288465,-0.625284 0.439594,0 0.776869,0.178111 0.341065,0.174322 0.621495,0.545703 z m -0.894346,2.747463 q 0.435804,0 0.66318,-0.318326 0.231166,-0.318327 0.231166,-0.924664 0,-0.606337 -0.231166,-0.924663 -0.227376,-0.318327 -0.66318,-0.318327 -0.432015,0 -0.663181,0.318327 -0.227376,0.318326 -0.227376,0.924663 0,0.606337 0.227376,0.924664 0.231166,0.318326 0.663181,0.318326 z" />
+ <path
+ id="path1235"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -38.116597,84.984456 q 0.344854,0 0.522965,-0.151584 0.178112,-0.151584 0.178112,-0.447173 0,-0.2918 -0.178112,-0.443384 -0.178111,-0.155374 -0.522965,-0.155374 h -0.807186 v 1.197515 z m 0.04926,2.474612 q 0.439594,0 0.659391,-0.185691 0.223586,-0.18569 0.223586,-0.560861 0,-0.367592 -0.219797,-0.549493 -0.219797,-0.18569 -0.66318,-0.18569 h -0.856451 v 1.481735 z m 1.356678,-2.035018 q 0.469911,0.136426 0.727604,0.504018 0.257693,0.367591 0.257693,0.901926 0,0.818554 -0.553282,1.220252 -0.553282,0.401698 -1.682584,0.401698 h -2.421558 v -5.657879 h 2.190392 q 1.178567,0 1.705322,0.356223 0.530544,0.356222 0.530544,1.140671 0,0.413066 -0.19327,0.704866 -0.193269,0.28801 -0.560861,0.428225 z" />
+ <path
+ id="path1237"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -30.291064,86.318397 v 0.38654 h -3.171899 q 0.04927,0.47749 0.344854,0.716235 0.295589,0.238745 0.826134,0.238745 0.428225,0 0.875399,-0.125057 0.450962,-0.128847 0.924663,-0.38654 v 1.045931 q -0.48128,0.181901 -0.96256,0.272852 -0.481279,0.09474 -0.962559,0.09474 -1.15204,0 -1.792483,-0.583599 -0.636653,-0.587389 -0.636653,-1.644689 0,-1.038351 0.625284,-1.633319 0.629075,-0.594968 1.72806,-0.594968 1.000455,0 1.599213,0.602547 0.602547,0.602547 0.602547,1.610582 z m -1.394574,-0.450963 q 0,-0.38654 -0.227377,-0.621495 -0.223586,-0.238745 -0.587388,-0.238745 -0.394119,0 -0.640443,0.223586 -0.246325,0.219798 -0.306958,0.636654 z" />
+ <path
+ id="path1239"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -24.996987,85.867434 v 2.58451 h -1.364258 V 88.031298 86.48135 q 0,-0.557072 -0.02653,-0.7655 -0.02274,-0.208428 -0.08337,-0.306958 -0.07958,-0.132636 -0.216008,-0.204639 -0.136425,-0.07579 -0.310747,-0.07579 -0.424436,0 -0.666971,0.329696 -0.242534,0.325906 -0.242534,0.905715 v 2.088072 h -1.356679 V 82.55532 h 1.356679 v 2.273762 q 0.306958,-0.371381 0.651812,-0.545703 0.344854,-0.178111 0.76171,-0.178111 0.735183,0 1.114144,0.450963 0.38275,0.450963 0.38275,1.311203 z" />
+ <path
+ id="path1241"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -21.836456,86.541984 q -0.424436,0 -0.640444,0.144005 -0.212217,0.144005 -0.212217,0.424435 0,0.257693 0.170532,0.405488 0.174322,0.144005 0.48128,0.144005 0.38275,0 0.644232,-0.272852 0.261483,-0.276641 0.261483,-0.689708 v -0.155373 z m 2.072913,-0.511597 v 2.421557 H -21.13159 V 87.82287 q -0.272852,0.38654 -0.613916,0.564651 -0.341064,0.174322 -0.829923,0.174322 -0.659391,0 -1.072458,-0.38275 -0.409278,-0.38654 -0.409278,-1.000456 0,-0.746552 0.511597,-1.095196 0.515386,-0.348643 1.614371,-0.348643 h 0.799607 v -0.106109 q 0,-0.322116 -0.253903,-0.469911 -0.253904,-0.151584 -0.792028,-0.151584 -0.435804,0 -0.810975,0.08716 -0.375171,0.08716 -0.697287,0.261482 v -1.034562 q 0.435804,-0.106108 0.875398,-0.159163 0.439594,-0.05684 0.879188,-0.05684 1.148251,0 1.656058,0.454753 0.511596,0.450962 0.511596,1.470366 z" />
+ <path
+ id="path1243"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -19.035938,84.207587 h 1.356678 l 1.0573,2.933154 1.05351,-2.933154 h 1.360468 l -1.671215,4.244357 h -1.489315 z" />
+ <path
+ id="path1245"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -13.442484,84.207587 h 1.356679 v 4.244357 h -1.356679 z m 0,-1.652267 h 1.356679 v 1.106564 h -1.356679 z" />
+ <path
+ id="path1247"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -8.7623213,85.075407 q -0.4509629,0 -0.689708,0.325906 -0.2349555,0.322116 -0.2349555,0.932242 0,0.610127 0.2349555,0.936033 0.2387451,0.322116 0.689708,0.322116 0.4433837,0 0.6783392,-0.322116 0.2349555,-0.325906 0.2349555,-0.936033 0,-0.610126 -0.2349555,-0.932242 -0.2349555,-0.325906 -0.6783392,-0.325906 z m 0,-0.970139 q 1.0951957,0 1.7091116,0.591178 0.6177055,0.591179 0.6177055,1.637109 0,1.045931 -0.6177055,1.637109 -0.6139159,0.591179 -1.7091116,0.591179 -1.0989853,0 -1.7204807,-0.591179 -0.617705,-0.591178 -0.617705,-1.637109 0,-1.04593 0.617705,-1.637109 0.6214954,-0.591178 1.7204807,-0.591178 z" />
+ <path
+ id="path1249"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -5.4956836,86.799677 v -2.59209 h 1.3642576 v 0.424436 q 0,0.344854 -0.00379,0.867819 -0.00379,0.519176 -0.00379,0.693498 0,0.511597 0.026527,0.738973 0.026527,0.223587 0.09095,0.325906 0.083371,0.132636 0.2160074,0.204638 0.1364258,0.072 0.3107476,0.072 0.4244357,0 0.6669703,-0.325906 0.2425347,-0.325906 0.2425347,-0.905715 v -2.095652 h 1.3566784 v 4.244357 h -1.3566784 v -0.613916 q -0.3069579,0.371382 -0.6518119,0.549493 -0.3410644,0.174322 -0.7541313,0.174322 -0.7351833,0 -1.1217229,-0.450963 -0.3827501,-0.450963 -0.3827501,-1.311203 z" />
+ <path
+ id="path1251"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m 3.2279882,85.363417 q -0.1781114,-0.08337 -0.3562228,-0.121268 -0.1743218,-0.04169 -0.3524332,-0.04169 -0.5229654,0 -0.8071857,0.337274 -0.2804308,0.333486 -0.2804308,0.95877 v 1.955436 H 0.07503736 V 84.207587 H 1.4317157 v 0.697288 q 0.2614827,-0.416857 0.5987575,-0.606337 0.3410644,-0.19327 0.814765,-0.19327 0.068213,0 0.1477946,0.0076 0.079582,0.0038 0.2311658,0.02274 z" />
+ </g>
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text1968"
+ aria-label="type">
+ <path
+ id="path1200"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -12.982713,110.86802 q -0.340778,0.22526 -0.825954,0.36965 -0.485175,0.1444 -1.051213,0.1444 -1.120524,0 -1.686562,-0.57759 -0.566038,-0.58336 -0.566038,-1.54794 v -3.08433 h -1.328456 v -1.08009 h 1.328456 v -1.34579 l 1.524837,-0.18482 v 1.53061 h 2.021564 l -0.155949,1.08009 h -1.865615 v 3.07855 q 0,0.47363 0.231036,0.69311 0.231036,0.21949 0.74509,0.21949 0.329227,0 0.600694,-0.0751 0.277243,-0.0809 0.502503,-0.20216 z" />
+ <path
+ id="path1202"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -5.7917378,105.09212 -2.0735471,6.12823 q -0.3754333,1.12052 -1.1147482,1.76742 -0.7393148,0.65268 -2.0677709,0.74509 l -0.190605,-1.1032 q 0.612245,-0.0866 0.981903,-0.25991 0.375433,-0.17328 0.5949171,-0.4563 0.22526,-0.28302 0.3869851,-0.70466 h -0.5198308 l -2.0042364,-6.11667 h 1.611475 l 1.3862158,5.10012 1.4439743,-5.10012 z" />
+ <path
+ id="path1204"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -1.2403471,104.91884 q 0.80284968,0 1.29380094,0.39854 0.49095126,0.39276 0.71043535,1.12052 0.22525999,0.72199 0.22525999,1.69812 0,0.94147 -0.27146716,1.67501 -0.27146717,0.73354 -0.79707382,1.15518 -0.51983075,0.41586 -1.2822492,0.41586 -0.9356953,0 -1.513285,-0.66423 v 2.84752 l -1.5248369,0.16172 v -8.63496 h 1.3400081 l 0.080863,0.74509 q 0.3581056,-0.47362 0.8086256,-0.69311 0.4562959,-0.22526 0.9299195,-0.22526 z m -0.4447441,1.14363 q -0.3869851,0 -0.6815559,0.23104 -0.2887948,0.23103 -0.5082789,0.57181 v 2.73777 q 0.4216405,0.6238 1.0743168,0.6238 0.5833657,0 0.88948821,-0.48517 0.31189844,-0.49096 0.31189844,-1.58838 0,-1.16095 -0.27724306,-1.62302 -0.27724309,-0.46785 -0.80862559,-0.46785 z" />
+ <path
+ id="path1206"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 3.8308738,108.61542 q 0.069311,0.8606 0.508279,1.24181 0.4389681,0.38121 1.0685409,0.38121 0.4389682,0 0.8259533,-0.13862 0.3869852,-0.13862 0.7624185,-0.38698 l 0.6353487,0.87216 q -0.4274164,0.3581 -1.0223338,0.57759 -0.5891416,0.21948 -1.2995769,0.21948 -0.9934543,0 -1.6750102,-0.41009 -0.67578,-0.41009 -1.0223338,-1.13785 -0.3465538,-0.72776 -0.3465538,-1.67501 0,-0.91259 0.335002,-1.64613 0.3407779,-0.73354 0.9819025,-1.16096 0.6469005,-0.43319 1.5537164,-0.43319 1.2591456,0 1.9984604,0.82018 0.7393148,0.82018 0.7393148,2.26993 0,0.335 -0.028879,0.60647 z m 1.3111287,-2.62226 q -0.5544862,0 -0.9125918,0.39854 -0.3523297,0.39853 -0.4158646,1.24759 h 2.5760502 q -0.011552,-0.77397 -0.3176744,-1.20716 -0.3061225,-0.43897 -0.9299194,-0.43897 z" />
+ </g>
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ id="text1972"
+ aria-label="instance">
+ <path
+ id="path1183"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 123.54934,104.04259 q 0.41586,0 0.68156,0.25991 0.26569,0.25992 0.26569,0.6469 0,0.38699 -0.26569,0.65268 -0.2657,0.25991 -0.68156,0.25991 -0.42164,0 -0.68733,-0.25991 -0.26569,-0.26569 -0.26569,-0.65268 0,-0.38698 0.26569,-0.6469 0.26569,-0.25991 0.68733,-0.25991 z m 0.98768,3.08433 v 5.03658 h 1.61147 v 1.08009 h -4.92684 v -1.08009 h 1.79053 v -3.95649 h -1.73277 v -1.08009 z" />
+ <path
+ id="path1185"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 127.95056,113.24359 v -6.11667 h 1.32845 l 0.10974,0.75664 q 0.7913,-0.92992 1.94071,-0.92992 0.82017,0 1.25337,0.4794 0.43896,0.47362 0.43896,1.33423 v 4.47632 h -1.52483 v -3.8814 q 0,-0.69311 -0.1444,-0.9819 -0.13862,-0.2888 -0.60069,-0.2888 -0.37544,0 -0.69889,0.23681 -0.32345,0.23681 -0.57759,0.57759 v 4.3377 z" />
+ <path
+ id="path1187"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 137.2093,112.29057 q 0.53716,0 0.86061,-0.18483 0.32923,-0.18483 0.32923,-0.53138 0,-0.21949 -0.10974,-0.37544 -0.10397,-0.16172 -0.41587,-0.29457 -0.3119,-0.13862 -0.93569,-0.30612 -0.58915,-0.15017 -1.03389,-0.36966 -0.43897,-0.22526 -0.68733,-0.57759 -0.24259,-0.35233 -0.24259,-0.88948 0,-0.79708 0.67001,-1.29958 0.67,-0.50828 1.87139,-0.50828 0.78552,0 1.37466,0.20793 0.58914,0.20216 1.01078,0.50828 l -0.6238,0.92992 q -0.36965,-0.23681 -0.80285,-0.38121 -0.42741,-0.15017 -0.92414,-0.15017 -0.53716,0 -0.78552,0.15595 -0.24259,0.15595 -0.24259,0.43319 0,0.19638 0.1213,0.335 0.12707,0.13285 0.45052,0.25992 0.32922,0.12129 0.93569,0.29457 0.59492,0.1675 1.03389,0.38698 0.44474,0.21949 0.68733,0.58337 0.24259,0.3581 0.24259,0.94724 0,0.66423 -0.38699,1.09743 -0.38698,0.43319 -1.02233,0.6469 -0.63535,0.20793 -1.36889,0.20793 -0.86639,0 -1.51329,-0.24837 -0.6469,-0.24836 -1.09742,-0.64112 l 0.7913,-0.88949 q 0.35811,0.28302 0.8144,0.46785 0.46207,0.18483 0.99923,0.18483 z" />
+ <path
+ id="path1189"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 147.09185,112.90281 q -0.34078,0.22526 -0.82596,0.36966 -0.48517,0.1444 -1.05121,0.1444 -1.12052,0 -1.68656,-0.57759 -0.56604,-0.58337 -0.56604,-1.54794 v -3.08433 h -1.32846 v -1.08009 h 1.32846 v -1.34579 l 1.52484,-0.18483 v 1.53062 h 2.02156 l -0.15595,1.08009 h -1.86561 v 3.07855 q 0,0.47363 0.23103,0.69311 0.23104,0.21948 0.74509,0.21948 0.32923,0 0.6007,-0.0751 0.27724,-0.0809 0.5025,-0.20216 z" />
+ <path
+ id="path1191"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 153.62437,111.63212 q 0,0.35233 0.10397,0.51405 0.10396,0.16173 0.335,0.23681 l -0.32923,1.02234 q -0.48517,-0.052 -0.83173,-0.24259 -0.34655,-0.19638 -0.53138,-0.58337 -0.34655,0.42164 -0.87794,0.62958 -0.5256,0.20793 -1.10319,0.20793 -0.9357,0 -1.48441,-0.53138 -0.54871,-0.53139 -0.54871,-1.38044 0,-0.97613 0.76242,-1.50174 0.7682,-0.53138 2.17174,-0.53138 h 0.85483 v -0.32923 q 0,-0.54293 -0.34078,-0.78552 -0.335,-0.24836 -0.9588,-0.24836 -0.29457,0 -0.73931,0.0809 -0.44474,0.0751 -0.90682,0.23681 l -0.36388,-1.04543 q 0.58337,-0.21949 1.17251,-0.32345 0.59492,-0.10397 1.08009,-0.10397 1.28803,0 1.91182,0.54871 0.6238,0.54293 0.6238,1.54216 z m -2.73777,0.68155 q 0.34655,0 0.69888,-0.1906 0.35233,-0.19638 0.56026,-0.55449 v -1.18983 h -0.60069 q -0.84906,0 -1.23027,0.27146 -0.37543,0.27147 -0.37543,0.7682 0,0.89526 0.94725,0.89526 z" />
+ <path
+ id="path1193"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 155.6748,113.24359 v -6.11667 h 1.32845 l 0.10974,0.75664 q 0.7913,-0.92992 1.94071,-0.92992 0.82017,0 1.25337,0.4794 0.43896,0.47362 0.43896,1.33423 v 4.47632 h -1.52483 v -3.8814 q 0,-0.69311 -0.1444,-0.9819 -0.13862,-0.2888 -0.60069,-0.2888 -0.37544,0 -0.69889,0.23681 -0.32345,0.23681 -0.57759,0.57759 v 4.3377 z" />
+ <path
+ id="path1195"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 165.68441,112.19238 q 0.40431,0 0.75664,-0.15018 0.35233,-0.15017 0.68733,-0.3812 l 0.69311,0.97612 q -0.40431,0.34078 -0.97612,0.56026 -0.57182,0.21949 -1.22449,0.21949 -0.96458,0 -1.65191,-0.39854 -0.68156,-0.39854 -1.04544,-1.12052 -0.36388,-0.72199 -0.36388,-1.67501 0,-0.94147 0.36966,-1.68079 0.37543,-0.73931 1.06276,-1.16095 0.69311,-0.42742 1.65191,-0.42742 0.65845,0 1.18983,0.1906 0.53716,0.18483 0.98191,0.55449 l -0.67578,0.9357 q -0.34078,-0.23104 -0.70466,-0.35811 -0.36388,-0.12707 -0.74509,-0.12707 -0.67578,0 -1.1032,0.49095 -0.42164,0.48518 -0.42164,1.5826 0,1.08587 0.43319,1.53061 0.43319,0.43897 1.08587,0.43897 z" />
+ <path
+ id="path1197"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 170.83649,110.65021 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38699 l 0.63535,0.87216 q -0.42742,0.35811 -1.02234,0.57759 -0.58914,0.21949 -1.29958,0.21949 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72777 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55372,-0.43319 1.25914,0 1.99846,0.82018 0.73931,0.82017 0.73931,2.26992 0,0.33501 -0.0289,0.60647 z m 1.31113,-2.62225 q -0.55448,0 -0.91259,0.39853 -0.35233,0.39854 -0.41586,1.2476 h 2.57605 q -0.0115,-0.77397 -0.31768,-1.20717 -0.30612,-0.43896 -0.92992,-0.43896 z" />
+ </g>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1974"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m -60.569299,125.94806 h 72.698771 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -72.698771 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text1980"
+ aria-label="ABC">
+ <path
+ id="path1176"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -29.753207,138.03049 h -2.628033 l -0.496728,1.83096 h -1.634579 l 2.500964,-7.98807 h 1.940701 l 2.495188,7.98807 h -1.680786 z m -2.345015,-1.18406 h 2.050444 l -1.022334,-3.78899 z" />
+ <path
+ id="path1178"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -21.112481,137.54532 q 0,0.67578 -0.265692,1.1263 -0.259915,0.44474 -0.710435,0.71043 -0.45052,0.25992 -1.022334,0.36966 -0.571814,0.10974 -1.184059,0.10974 h -2.47786 v -7.98807 h 2.333463 q 0.779746,0 1.455526,0.18483 0.681556,0.18483 1.103196,0.62958 0.421641,0.43896 0.421641,1.21871 0,0.49095 -0.207932,0.84328 -0.202157,0.34656 -0.542935,0.56604 -0.335002,0.21948 -0.721987,0.31767 0.433192,0.0693 0.849057,0.27147 0.42164,0.19638 0.693108,0.59492 0.277243,0.39276 0.277243,1.04544 z m -1.946478,-3.5002 q 0,-0.54293 -0.340778,-0.77974 -0.340778,-0.23682 -0.993454,-0.23682 h -0.797074 v 2.10821 h 0.866385 q 0.641124,0 0.953023,-0.25414 0.311898,-0.25992 0.311898,-0.83751 z m 0.306123,3.45976 q 0,-0.72776 -0.415865,-0.98767 -0.410088,-0.2657 -1.039661,-0.2657 h -0.981903 v 2.42588 h 0.912592 q 0.381209,0 0.727763,-0.0866 0.35233,-0.0924 0.571814,-0.34078 0.22526,-0.25413 0.22526,-0.74509 z" />
+ <path
+ id="path1180"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -16.514884,131.70011 q 0.83173,0 1.409319,0.21948 0.57759,0.21371 1.068541,0.61802 l -0.802849,0.95303 q -0.346554,-0.28302 -0.750867,-0.4332 -0.404313,-0.15595 -0.866385,-0.15595 -0.560262,0 -1.028109,0.29457 -0.462072,0.29458 -0.739315,0.94725 -0.277243,0.6469 -0.277243,1.70967 0,1.04543 0.265691,1.69234 0.271467,0.64112 0.733539,0.94147 0.467848,0.30034 1.056989,0.30034 0.623797,0 1.033886,-0.2137 0.415864,-0.21949 0.739315,-0.48518 l 0.74509,0.94147 q -0.42164,0.41587 -1.056989,0.71044 -0.629573,0.29457 -1.530613,0.29457 -1.045437,0 -1.865614,-0.47363 -0.820178,-0.4794 -1.288025,-1.40932 -0.467848,-0.93569 -0.467848,-2.2988 0,-1.34001 0.479399,-2.26415 0.485176,-0.92992 1.305353,-1.40932 0.825953,-0.4794 1.836735,-0.4794 z" />
+ </g>
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ id="text1984"
+ aria-label="instance">
+ <path
+ id="path1159"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 183.76608,131.26282 q 0.41587,0 0.68156,0.25991 0.26569,0.25992 0.26569,0.6469 0,0.38699 -0.26569,0.65268 -0.26569,0.25991 -0.68156,0.25991 -0.42164,0 -0.68733,-0.25991 -0.26569,-0.26569 -0.26569,-0.65268 0,-0.38698 0.26569,-0.6469 0.26569,-0.25991 0.68733,-0.25991 z m 0.98768,3.08433 v 5.03658 h 1.61148 v 1.08009 h -4.92684 v -1.08009 h 1.79052 v -3.95649 h -1.73276 v -1.08009 z" />
+ <path
+ id="path1161"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 188.1673,140.46382 v -6.11667 h 1.32846 l 0.10974,0.75664 q 0.7913,-0.92992 1.9407,-0.92992 0.82018,0 1.25337,0.4794 0.43897,0.47362 0.43897,1.33423 v 4.47632 h -1.52484 v -3.8814 q 0,-0.69311 -0.1444,-0.9819 -0.13862,-0.2888 -0.60069,-0.2888 -0.37543,0 -0.69888,0.23681 -0.32345,0.23681 -0.57759,0.57759 v 4.3377 z" />
+ <path
+ id="path1163"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 197.42605,139.5108 q 0.53716,0 0.86061,-0.18483 0.32922,-0.18483 0.32922,-0.53138 0,-0.21949 -0.10974,-0.37544 -0.10397,-0.16172 -0.41586,-0.29457 -0.3119,-0.13862 -0.9357,-0.30612 -0.58914,-0.15017 -1.03389,-0.36966 -0.43896,-0.22526 -0.68733,-0.57759 -0.24259,-0.35233 -0.24259,-0.88948 0,-0.79708 0.67001,-1.29958 0.67,-0.50828 1.87139,-0.50828 0.78552,0 1.37466,0.20793 0.58914,0.20216 1.01078,0.50828 l -0.62379,0.92992 q -0.36966,-0.23681 -0.80285,-0.38121 -0.42742,-0.15017 -0.92415,-0.15017 -0.53715,0 -0.78552,0.15595 -0.24258,0.15595 -0.24258,0.43319 0,0.19638 0.12129,0.335 0.12707,0.13285 0.45052,0.25992 0.32923,0.12129 0.93569,0.29457 0.59492,0.1675 1.03389,0.38698 0.44474,0.21949 0.68733,0.58337 0.24259,0.3581 0.24259,0.94725 0,0.66422 -0.38699,1.09742 -0.38698,0.43319 -1.02233,0.6469 -0.63535,0.20793 -1.36889,0.20793 -0.86638,0 -1.51328,-0.24837 -0.6469,-0.24836 -1.09742,-0.64112 l 0.7913,-0.88949 q 0.3581,0.28302 0.8144,0.46785 0.46207,0.18483 0.99923,0.18483 z" />
+ <path
+ id="path1165"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 207.30859,140.12304 q -0.34078,0.22526 -0.82595,0.36966 -0.48518,0.1444 -1.05122,0.1444 -1.12052,0 -1.68656,-0.57759 -0.56604,-0.58337 -0.56604,-1.54794 v -3.08433 h -1.32845 v -1.08009 h 1.32845 v -1.34579 l 1.52484,-0.18483 v 1.53062 h 2.02156 l -0.15594,1.08009 h -1.86562 v 3.07855 q 0,0.47363 0.23104,0.69311 0.23103,0.21948 0.74509,0.21948 0.32922,0 0.60069,-0.0751 0.27724,-0.0809 0.5025,-0.20216 z" />
+ <path
+ id="path1167"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 213.84111,138.85235 q 0,0.35233 0.10397,0.51405 0.10397,0.16173 0.335,0.23681 l -0.32922,1.02234 q -0.48518,-0.052 -0.83173,-0.24259 -0.34656,-0.19638 -0.53139,-0.58337 -0.34655,0.42164 -0.87793,0.62958 -0.52561,0.20793 -1.1032,0.20793 -0.93569,0 -1.4844,-0.53138 -0.54871,-0.53139 -0.54871,-1.38044 0,-0.97613 0.76241,-1.50174 0.7682,-0.53138 2.17174,-0.53138 h 0.85483 v -0.32923 q 0,-0.54293 -0.34077,-0.78552 -0.33501,-0.24836 -0.9588,-0.24836 -0.29457,0 -0.73932,0.0809 -0.44474,0.0751 -0.90681,0.23681 l -0.36388,-1.04543 q 0.58336,-0.21949 1.1725,-0.32345 0.59492,-0.10397 1.0801,-0.10397 1.28802,0 1.91182,0.54871 0.62379,0.54293 0.62379,1.54216 z m -2.73777,0.68155 q 0.34655,0 0.69888,-0.1906 0.35233,-0.19638 0.56026,-0.55449 v -1.18983 h -0.60069 q -0.84906,0 -1.23027,0.27146 -0.37543,0.27147 -0.37543,0.7682 0,0.89526 0.94725,0.89526 z" />
+ <path
+ id="path1169"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 215.89154,140.46382 v -6.11667 H 217.22 l 0.10974,0.75664 q 0.7913,-0.92992 1.9407,-0.92992 0.82018,0 1.25337,0.4794 0.43897,0.47362 0.43897,1.33423 v 4.47632 h -1.52484 v -3.8814 q 0,-0.69311 -0.1444,-0.9819 -0.13862,-0.2888 -0.60069,-0.2888 -0.37543,0 -0.69888,0.23681 -0.32345,0.23681 -0.57759,0.57759 v 4.3377 z" />
+ <path
+ id="path1171"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 225.90115,139.41261 q 0.40432,0 0.75665,-0.15018 0.35233,-0.15017 0.68733,-0.3812 l 0.69311,0.97612 q -0.40432,0.34078 -0.97613,0.56026 -0.57181,0.21949 -1.22449,0.21949 -0.96458,0 -1.65191,-0.39854 -0.68155,-0.39854 -1.04544,-1.12052 -0.36388,-0.72199 -0.36388,-1.67501 0,-0.94147 0.36966,-1.68079 0.37543,-0.73931 1.06277,-1.16095 0.6931,-0.42742 1.6519,-0.42742 0.65845,0 1.18984,0.1906 0.53716,0.18483 0.9819,0.55449 l -0.67578,0.9357 q -0.34078,-0.23104 -0.70466,-0.35811 -0.36388,-0.12707 -0.74509,-0.12707 -0.67578,0 -1.1032,0.49095 -0.42164,0.48518 -0.42164,1.5826 0,1.08587 0.4332,1.53061 0.43319,0.43897 1.08586,0.43897 z" />
+ <path
+ id="path1173"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ d="m 231.05324,137.87044 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82595,-0.13862 0.38699,-0.13862 0.76242,-0.38699 l 0.63535,0.87216 q -0.42742,0.35811 -1.02234,0.57759 -0.58914,0.21949 -1.29957,0.21949 -0.99346,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02234,-1.13785 -0.34655,-0.72777 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16096 0.64691,-0.43319 1.55372,-0.43319 1.25915,0 1.99846,0.82018 0.73932,0.82017 0.73932,2.26992 0,0.33501 -0.0289,0.60647 z m 1.31113,-2.62225 q -0.55449,0 -0.91259,0.39853 -0.35233,0.39854 -0.41587,1.2476 h 2.57605 q -0.0115,-0.77397 -0.31767,-1.20717 -0.30613,-0.43896 -0.92992,-0.43896 z" />
+ </g>
+ <path
+ d="M 17.347598,126.00309 H 170.2081 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 17.347598 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path1986"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text1990"
+ aria-label="type">
+ <path
+ id="path1150"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 86.078604,138.14328 q -0.340778,0.22526 -0.825953,0.36965 -0.485176,0.1444 -1.051214,0.1444 -1.120524,0 -1.686562,-0.57759 -0.566038,-0.58336 -0.566038,-1.54794 v -3.08433 h -1.328456 v -1.08009 h 1.328456 v -1.34578 l 1.524837,-0.18483 v 1.53061 h 2.021564 l -0.155949,1.08009 h -1.865615 v 3.07856 q 0,0.47362 0.231036,0.6931 0.231036,0.21949 0.745091,0.21949 0.329226,0 0.600693,-0.0751 0.277243,-0.0809 0.502503,-0.20216 z" />
+ <path
+ id="path1152"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 93.26958,132.36738 -2.073547,6.12823 q -0.375434,1.12052 -1.114749,1.76742 -0.739314,0.65268 -2.067771,0.74509 l -0.190604,-1.10319 q 0.612245,-0.0866 0.981902,-0.25992 0.375433,-0.17328 0.594918,-0.4563 0.22526,-0.28301 0.386985,-0.70466 h -0.519831 l -2.004236,-6.11667 h 1.611475 l 1.386215,5.10012 1.443974,-5.10012 z" />
+ <path
+ id="path1154"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 97.82097,132.1941 q 0.80285,0 1.293801,0.39854 0.490952,0.39276 0.710436,1.12052 0.225263,0.72199 0.225263,1.69812 0,0.94147 -0.271471,1.67501 -0.271467,0.73354 -0.797073,1.15518 -0.519831,0.41586 -1.28225,0.41586 -0.935695,0 -1.513285,-0.66423 v 2.84752 l -1.524836,0.16173 v -8.63497 h 1.340008 l 0.08086,0.74509 q 0.358106,-0.47362 0.808626,-0.69311 0.456296,-0.22526 0.929919,-0.22526 z m -0.444744,1.14363 q -0.386985,0 -0.681556,0.23104 -0.288795,0.23103 -0.508279,0.57181 v 2.73778 q 0.421641,0.62379 1.074317,0.62379 0.583366,0 0.889488,-0.48517 0.311899,-0.49095 0.311899,-1.58838 0,-1.16095 -0.277243,-1.62302 -0.277243,-0.46785 -0.808626,-0.46785 z" />
+ <path
+ id="path1156"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 102.89219,135.89068 q 0.0693,0.86061 0.50828,1.24181 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82595,-0.13862 0.38699,-0.13862 0.76242,-0.38698 l 0.63535,0.87216 q -0.42741,0.3581 -1.02233,0.57759 -0.58914,0.21948 -1.29958,0.21948 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34656,-0.72776 -0.34656,-1.67501 0,-0.91259 0.33501,-1.64613 0.34077,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55371,-0.43319 1.25915,0 1.99846,0.82018 0.73932,0.82018 0.73932,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55449,0 -0.91259,0.39854 -0.35233,0.39853 -0.41587,1.24759 h 2.57605 q -0.0115,-0.77397 -0.31767,-1.20716 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ </g>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1992"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="M -60.569299,153.16829 H 49.987465 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H -60.569299 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text1998"
+ aria-label="DType">
+ <path
+ id="path1139"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -16.103363,161.78806 q 0,1.23027 -0.32345,2.02157 -0.323451,0.78552 -0.866385,1.22449 -0.542934,0.43897 -1.218714,0.61224 -0.670004,0.17328 -1.368888,0.17328 h -2.044668 v -7.98806 h 1.906046 q 0.745091,0 1.443975,0.16172 0.698883,0.15595 1.253369,0.57759 0.560262,0.42164 0.889489,1.20139 0.329226,0.77397 0.329226,2.01578 z m -1.651907,0 q 0,-0.88948 -0.167501,-1.43819 -0.161725,-0.54871 -0.444744,-0.83751 -0.283019,-0.29457 -0.641125,-0.39854 -0.358105,-0.10396 -0.74509,-0.10396 h -0.589142 v 5.63727 h 0.594918 q 0.542934,0 0.993454,-0.23681 0.45052,-0.23681 0.721987,-0.85483 0.277243,-0.6238 0.277243,-1.76743 z" />
+ <path
+ id="path1141"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -11.482662,159.07339 v 6.74625 h -1.57682 v -6.74625 h -2.333462 v -1.24181 h 6.3130554 l -0.1617251,1.24181 z" />
+ <path
+ id="path1143"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -2.3221052,159.70297 -2.0735471,6.12822 q -0.3754333,1.12053 -1.1147481,1.76743 -0.7393149,0.65267 -2.0677712,0.74509 l -0.1906046,-1.1032 q 0.6122451,-0.0866 0.9819025,-0.25991 0.3754333,-0.17328 0.5949174,-0.4563 0.22526,-0.28302 0.3869851,-0.70466 h -0.5198307 l -2.0042364,-6.11667 h 1.6114754 l 1.3862153,5.10011 1.4439743,-5.10011 z" />
+ <path
+ id="path1145"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 2.229285,159.52969 q 0.8028497,0 1.293801,0.39854 0.4909512,0.39276 0.7104353,1.12052 0.22526,0.72199 0.22526,1.69811 0,0.94148 -0.2714671,1.67501 -0.2714672,0.73354 -0.7970738,1.15518 -0.5198308,0.41587 -1.2822492,0.41587 -0.9356954,0 -1.51328509,-0.66423 v 2.84752 l -1.52483686,0.16172 v -8.63496 H 0.4098774 l 0.0808626,0.74509 q 0.35810562,-0.47363 0.80862564,-0.69311 0.4562958,-0.22526 0.9299194,-0.22526 z m -0.4447441,1.14363 q -0.3869851,0 -0.6815558,0.23103 -0.2887949,0.23104 -0.50827899,0.57182 v 2.73777 q 0.42164049,0.6238 1.07431689,0.6238 0.5833656,0 0.8894882,-0.48518 0.3118984,-0.49095 0.3118984,-1.58837 0,-1.16095 -0.2772431,-1.62303 -0.277243,-0.46784 -0.8086256,-0.46784 z" />
+ <path
+ id="path1147"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 7.3005069,163.22626 q 0.069311,0.86061 0.508279,1.24182 0.4389681,0.38121 1.0685409,0.38121 0.4389682,0 0.8259533,-0.13862 0.3869849,-0.13862 0.7624189,-0.38699 l 0.635348,0.87216 q -0.427416,0.35811 -1.022334,0.57759 -0.5891411,0.21949 -1.2995764,0.21949 -0.9934543,0 -1.6750102,-0.41009 -0.67578,-0.41009 -1.0223338,-1.13785 -0.3465538,-0.72777 -0.3465538,-1.67501 0,-0.91259 0.335002,-1.64613 0.3407779,-0.73354 0.9819025,-1.16096 0.6469005,-0.43319 1.5537164,-0.43319 1.2591456,0 1.9984603,0.82018 0.739315,0.82017 0.739315,2.26992 0,0.33501 -0.02888,0.60647 z m 1.3111287,-2.62225 q -0.5544862,0 -0.9125918,0.39853 -0.3523297,0.39854 -0.4158646,1.2476 h 2.5760502 q -0.011552,-0.77397 -0.3176744,-1.20717 -0.3061225,-0.43896 -0.9299194,-0.43896 z" />
+ </g>
+ <path
+ d="m -60.569299,180.38852 h 72.698771 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -72.698771 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 V 182.4536 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2004"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <path
+ d="m 175.57697,180.55362 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2006"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text2010"
+ aria-label="base dtype">
+ <path
+ id="path1120"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -56.5562,187.97729 q 0.306123,-0.39854 0.721988,-0.62957 0.42164,-0.23104 0.906816,-0.23104 1.19561,0 1.732769,0.87794 0.537158,0.87216 0.537158,2.33923 0,0.94148 -0.277243,1.67501 -0.277243,0.73354 -0.825953,1.15518 -0.542935,0.41587 -1.334233,0.41587 -0.99923,0 -1.565268,-0.75664 l -0.06931,0.58336 h -1.35156 v -8.55988 l 1.524836,-0.16172 z m 1.068541,4.46477 q 0.583366,0 0.912592,-0.49673 0.329226,-0.49673 0.329226,-1.59415 0,-1.16095 -0.300346,-1.62303 -0.300347,-0.46784 -0.825954,-0.46784 -0.381209,0 -0.67578,0.23103 -0.288794,0.23104 -0.508279,0.57182 v 2.73777 q 0.196381,0.30612 0.462072,0.47363 0.265692,0.1675 0.606469,0.1675 z" />
+ <path
+ id="path1122"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -46.269343,191.79516 q 0,0.35233 0.103966,0.51405 0.103966,0.16173 0.335002,0.23681 l -0.329226,1.02234 q -0.485175,-0.052 -0.831729,-0.24259 -0.346554,-0.19638 -0.531383,-0.58337 -0.346553,0.42164 -0.877936,0.62958 -0.525607,0.20793 -1.103196,0.20793 -0.935696,0 -1.484406,-0.53138 -0.54871,-0.53139 -0.54871,-1.38044 0,-0.97613 0.762418,-1.50174 0.768195,-0.53138 2.171738,-0.53138 h 0.854832 v -0.32923 q 0,-0.54293 -0.340778,-0.78552 -0.335002,-0.24836 -0.958798,-0.24836 -0.294571,0 -0.739315,0.0809 -0.444744,0.0751 -0.906816,0.23681 l -0.363882,-1.04543 q 0.583366,-0.21949 1.172507,-0.32345 0.594918,-0.10397 1.080093,-0.10397 1.288025,0 1.911822,0.54871 0.623797,0.54293 0.623797,1.54216 z m -2.737775,0.68155 q 0.346554,0 0.698883,-0.1906 0.35233,-0.19638 0.560262,-0.55449 v -1.18983 h -0.600693 q -0.849057,0 -1.230266,0.27146 -0.375433,0.27147 -0.375433,0.7682 0,0.89526 0.947247,0.89526 z" />
+ <path
+ id="path1124"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -41.891229,192.45361 q 0.537158,0 0.860609,-0.18483 0.329226,-0.18483 0.329226,-0.53138 0,-0.21949 -0.109742,-0.37544 -0.103967,-0.16172 -0.415865,-0.29457 -0.311898,-0.13862 -0.935695,-0.30612 -0.589142,-0.15017 -1.033886,-0.36966 -0.438968,-0.22526 -0.687332,-0.57759 -0.242587,-0.35233 -0.242587,-0.88948 0,-0.79708 0.670004,-1.29958 0.670004,-0.50828 1.87139,-0.50828 0.785522,0 1.374664,0.20793 0.589141,0.20216 1.010782,0.50828 l -0.623797,0.92992 q -0.369657,-0.23681 -0.80285,-0.38121 -0.427416,-0.15017 -0.924143,-0.15017 -0.537159,0 -0.785522,0.15595 -0.242588,0.15595 -0.242588,0.43319 0,0.19638 0.121294,0.335 0.12707,0.13285 0.45052,0.25992 0.329226,0.12129 0.935695,0.29457 0.594918,0.1675 1.033886,0.38698 0.444744,0.21949 0.687332,0.58337 0.242587,0.3581 0.242587,0.94725 0,0.66422 -0.386985,1.09742 -0.386985,0.43319 -1.022334,0.6469 -0.635348,0.20793 -1.368887,0.20793 -0.866385,0 -1.513285,-0.24837 -0.646901,-0.24836 -1.097421,-0.64112 l 0.791298,-0.88949 q 0.358106,0.28302 0.814402,0.46785 0.462071,0.18483 0.99923,0.18483 z" />
+ <path
+ id="path1126"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -35.988279,190.81325 q 0.06931,0.86061 0.508279,1.24182 0.438968,0.38121 1.068541,0.38121 0.438968,0 0.825953,-0.13862 0.386985,-0.13862 0.762419,-0.38699 l 0.635348,0.87216 q -0.427416,0.35811 -1.022333,0.57759 -0.589142,0.21949 -1.299577,0.21949 -0.993455,0 -1.675011,-0.41009 -0.67578,-0.41009 -1.022333,-1.13785 -0.346554,-0.72777 -0.346554,-1.67501 0,-0.91259 0.335002,-1.64613 0.340778,-0.73354 0.981902,-1.16096 0.646901,-0.43319 1.553717,-0.43319 1.259145,0 1.99846,0.82018 0.739315,0.82017 0.739315,2.26992 0,0.33501 -0.02888,0.60647 z m 1.311129,-2.62225 q -0.554486,0 -0.912592,0.39853 -0.35233,0.39854 -0.415865,1.2476 h 2.57605 q -0.01155,-0.77397 -0.317674,-1.20717 -0.306122,-0.43896 -0.929919,-0.43896 z" />
+ <path
+ id="path1128"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -19.879335,184.68503 1.524837,0.16172 v 8.55988 h -1.35156 l -0.09242,-0.72199 q -0.283019,0.40432 -0.710435,0.65268 -0.427417,0.24259 -0.993454,0.24259 -0.773971,0 -1.28225,-0.40431 -0.502503,-0.40432 -0.750866,-1.13208 -0.242588,-0.73354 -0.242588,-1.70389 0,-0.92992 0.288795,-1.65768 0.294571,-0.73354 0.837505,-1.14941 0.542934,-0.41586 1.293801,-0.41586 0.895264,0 1.47863,0.61802 z m -1.068541,3.5695 q -0.57759,0 -0.912592,0.5025 -0.329226,0.49673 -0.329226,1.58838 0,1.15518 0.306122,1.62302 0.306123,0.46785 0.825954,0.46785 0.381209,0 0.670004,-0.22526 0.288795,-0.23104 0.508279,-0.57181 v -2.78399 q -0.213709,-0.28301 -0.4794,-0.43896 -0.259915,-0.16173 -0.589141,-0.16173 z" />
+ <path
+ id="path1130"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -11.215505,193.06585 q -0.340778,0.22526 -0.825954,0.36966 -0.485175,0.1444 -1.051213,0.1444 -1.120524,0 -1.686562,-0.57759 -0.566038,-0.58337 -0.566038,-1.54794 v -3.08433 h -1.328456 v -1.08009 h 1.328456 v -1.34579 l 1.524837,-0.18483 v 1.53062 h 2.021564 l -0.155949,1.08009 h -1.865615 v 3.07855 q 0,0.47363 0.231036,0.69311 0.231036,0.21948 0.745091,0.21948 0.329226,0 0.600693,-0.0751 0.277243,-0.0809 0.502503,-0.20216 z" />
+ <path
+ id="path1132"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m -4.0245292,187.28996 -2.0735471,6.12822 q -0.3754333,1.12053 -1.1147482,1.76743 -0.7393148,0.65267 -2.0677712,0.74509 l -0.1906046,-1.1032 q 0.6122451,-0.0866 0.9819025,-0.25991 0.3754334,-0.17328 0.5949175,-0.4563 0.2252599,-0.28302 0.3869851,-0.70466 H -8.027226 l -2.004236,-6.11667 h 1.611475 l 1.3862153,5.10011 1.4439743,-5.10011 z" />
+ <path
+ id="path1134"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 0.52686192,187.11668 q 0.80284968,0 1.29380098,0.39854 0.4909513,0.39276 0.7104353,1.12052 0.22526,0.72199 0.22526,1.69811 0,0.94148 -0.2714671,1.67501 -0.2714672,0.73354 -0.7970738,1.15518 -0.5198308,0.41587 -1.28224922,0.41587 -0.93569535,0 -1.51328508,-0.66423 v 2.84752 l -1.5248368,0.16172 v -8.63496 h 1.3400081 l 0.080863,0.74509 q 0.35810559,-0.47363 0.80862557,-0.69311 0.45629588,-0.22526 0.92991945,-0.22526 z m -0.44474409,1.14363 q -0.38698511,0 -0.68155586,0.23103 -0.28879486,0.23104 -0.50827897,0.57182 v 2.73777 q 0.42164051,0.6238 1.07431689,0.6238 0.58336562,0 0.88948817,-0.48518 0.31189844,-0.49095 0.31189844,-1.58837 0,-1.16095 -0.27724306,-1.62303 -0.27724306,-0.46784 -0.80862561,-0.46784 z" />
+ <path
+ id="path1136"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 5.5980838,190.81325 q 0.069311,0.86061 0.508279,1.24182 0.4389682,0.38121 1.0685409,0.38121 0.4389682,0 0.8259533,-0.13862 0.3869852,-0.13862 0.7624185,-0.38699 l 0.6353487,0.87216 q -0.4274164,0.35811 -1.0223338,0.57759 -0.5891416,0.21949 -1.2995769,0.21949 -0.9934543,0 -1.6750102,-0.41009 -0.67578,-0.41009 -1.0223338,-1.13785 -0.3465538,-0.72777 -0.3465538,-1.67501 0,-0.91259 0.335002,-1.64613 0.3407779,-0.73354 0.9819025,-1.16096 0.6469005,-0.43319 1.5537164,-0.43319 1.2591456,0 1.9984604,0.82018 0.7393149,0.82017 0.7393149,2.26992 0,0.33501 -0.02888,0.60647 z M 6.9092125,188.191 q -0.5544862,0 -0.9125918,0.39853 -0.3523297,0.39854 -0.4158646,1.2476 H 8.1568063 Q 8.1452545,189.06316 7.8391319,188.62996 7.5330094,188.191 6.9092125,188.191 Z" />
+ </g>
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ id="text2014"
+ aria-label="element">
+ <path
+ id="path1105"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 186.26703,191.99035 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.3812 1.06854,0.3812 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76241,-0.38698 l 0.63535,0.87216 q -0.42741,0.3581 -1.02233,0.57759 -0.58914,0.21948 -1.29958,0.21948 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34656,-0.72776 -0.34656,-1.67501 0,-0.91259 0.33501,-1.64613 0.34077,-0.73354 0.9819,-1.16095 0.6469,-0.4332 1.55372,-0.4332 1.25914,0 1.99846,0.82018 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39853 -0.41586,1.24759 h 2.57605 q -0.0116,-0.77397 -0.31768,-1.20716 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1107"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 194.80957,186.02385 v 6.7809 q 0,0.39854 0.23681,0.56604 0.23681,0.1675 0.62957,0.1675 0.24837,0 0.4794,-0.052 0.23104,-0.0577 0.43897,-0.13862 l 0.37543,1.03966 q -0.28879,0.15018 -0.70466,0.25992 -0.41008,0.10974 -0.95302,0.10974 -0.99923,0 -1.51328,-0.57181 -0.51406,-0.57182 -0.51406,-1.54217 v -5.53908 h -1.83096 v -1.08009 z" />
+ <path
+ id="path1109"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 200.12915,191.99035 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.3812 1.06854,0.3812 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38698 l 0.63534,0.87216 q -0.42741,0.3581 -1.02233,0.57759 -0.58914,0.21948 -1.29958,0.21948 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72776 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16095 0.6469,-0.4332 1.55372,-0.4332 1.25914,0 1.99846,0.82018 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39853 -0.41586,1.24759 h 2.57605 q -0.0116,-0.77397 -0.31768,-1.20716 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1111"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 210.10989,188.29377 q 0.57759,0 0.91259,0.38699 0.335,0.38121 0.335,1.36889 v 4.53407 h -1.32846 v -4.34347 q 0,-0.41009 -0.0635,-0.58337 -0.0635,-0.17905 -0.30035,-0.17905 -0.1906,0 -0.38698,0.11552 -0.19638,0.10974 -0.39854,0.39854 v 4.59183 h -1.1494 v -4.34347 q 0,-0.41009 -0.0635,-0.58337 -0.0635,-0.17905 -0.30034,-0.17905 -0.19061,0 -0.38699,0.11552 -0.19638,0.10974 -0.39854,0.39854 v 4.59183 h -1.34578 v -6.11667 h 1.13785 l 0.0982,0.63535 q 0.27147,-0.37543 0.57182,-0.58914 0.30034,-0.21949 0.72198,-0.21949 0.34656,0 0.61225,0.17328 0.27147,0.1675 0.38698,0.57759 0.26569,-0.335 0.58914,-0.54293 0.32923,-0.20794 0.75665,-0.20794 z" />
+ <path
+ id="path1113"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 213.99127,191.99035 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.3812 1.06854,0.3812 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38698 l 0.63534,0.87216 q -0.42741,0.3581 -1.02233,0.57759 -0.58914,0.21948 -1.29958,0.21948 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72776 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16095 0.6469,-0.4332 1.55372,-0.4332 1.25914,0 1.99846,0.82018 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39853 -0.41586,1.24759 H 216.55 q -0.0116,-0.77397 -0.31768,-1.20716 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1115"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 219.62276,194.58372 v -6.11667 h 1.32845 l 0.10974,0.75664 q 0.7913,-0.92992 1.94071,-0.92992 0.82017,0 1.25337,0.4794 0.43896,0.47363 0.43896,1.33423 v 4.47632 h -1.52483 v -3.8814 q 0,-0.69311 -0.1444,-0.9819 -0.13862,-0.2888 -0.60069,-0.2888 -0.37544,0 -0.69889,0.23682 -0.32345,0.23681 -0.57759,0.57759 v 4.33769 z" />
+ <path
+ id="path1117"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 231.83299,194.24295 q -0.34078,0.22526 -0.82596,0.36965 -0.48517,0.1444 -1.05121,0.1444 -1.12052,0 -1.68656,-0.57759 -0.56604,-0.58336 -0.56604,-1.54794 v -3.08433 h -1.32846 v -1.08009 h 1.32846 v -1.34578 l 1.52484,-0.18483 v 1.53061 h 2.02156 l -0.15595,1.08009 h -1.86561 v 3.07856 q 0,0.47362 0.23103,0.6931 0.23104,0.21949 0.74509,0.21949 0.32923,0 0.6007,-0.0751 0.27724,-0.0809 0.5025,-0.20216 z" />
+ </g>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path2016"
+ style="opacity:0.25;fill:#000081;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="M 17.463123,180.38852 H 170.32495 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 17.463123 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 V 182.4536 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ id="text2020"
+ aria-label="dtype">
+ <path
+ id="path1094"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 81.083132,184.68503 1.524837,0.16172 v 8.55988 h -1.35156 l -0.09242,-0.72199 q -0.283019,0.40432 -0.710435,0.65268 -0.427416,0.24259 -0.993454,0.24259 -0.77397,0 -1.282249,-0.40431 -0.502503,-0.40432 -0.750867,-1.13208 -0.242588,-0.73354 -0.242588,-1.70389 0,-0.92992 0.288795,-1.65768 0.294571,-0.73354 0.837505,-1.14941 0.542935,-0.41586 1.293801,-0.41586 0.895264,0 1.47863,0.61802 z m -1.068541,3.5695 q -0.57759,0 -0.912592,0.5025 -0.329226,0.49673 -0.329226,1.58838 0,1.15518 0.306123,1.62302 0.306122,0.46785 0.825953,0.46785 0.381209,0 0.670004,-0.22526 0.288795,-0.23104 0.508279,-0.57181 v -2.78399 q -0.213708,-0.28301 -0.4794,-0.43896 -0.259915,-0.16173 -0.589141,-0.16173 z" />
+ <path
+ id="path1096"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 89.746961,193.06585 q -0.340778,0.22526 -0.825953,0.36966 -0.485175,0.1444 -1.051213,0.1444 -1.120524,0 -1.686562,-0.57759 -0.566038,-0.58337 -0.566038,-1.54794 v -3.08433 h -1.328457 v -1.08009 h 1.328457 v -1.34579 l 1.524837,-0.18483 v 1.53062 h 2.021564 l -0.15595,1.08009 h -1.865614 v 3.07855 q 0,0.47363 0.231036,0.69311 0.231035,0.21948 0.74509,0.21948 0.329226,0 0.600694,-0.0751 0.277243,-0.0809 0.502503,-0.20216 z" />
+ <path
+ id="path1098"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 96.937937,187.28996 -2.073547,6.12822 q -0.375433,1.12053 -1.114748,1.76743 -0.739315,0.65267 -2.067771,0.74509 l -0.190605,-1.1032 q 0.612245,-0.0866 0.981902,-0.25991 0.375434,-0.17328 0.594918,-0.4563 0.22526,-0.28302 0.386985,-0.70466 H 92.93524 l -2.004236,-6.11667 h 1.611475 l 1.386216,5.10011 1.443974,-5.10011 z" />
+ <path
+ id="path1100"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 101.48933,187.11668 q 0.80285,0 1.2938,0.39854 0.49095,0.39276 0.71043,1.12052 0.22526,0.72199 0.22526,1.69811 0,0.94148 -0.27146,1.67501 -0.27147,0.73354 -0.79708,1.15518 -0.51983,0.41587 -1.28225,0.41587 -0.93569,0 -1.513282,-0.66423 v 2.84752 l -1.524837,0.16172 v -8.63496 h 1.340009 l 0.08086,0.74509 q 0.358108,-0.47363 0.808628,-0.69311 0.45629,-0.22526 0.92992,-0.22526 z m -0.44475,1.14363 q -0.38698,0 -0.68155,0.23103 -0.2888,0.23104 -0.508282,0.57182 v 2.73777 q 0.421642,0.6238 1.074322,0.6238 0.58336,0 0.88948,-0.48518 0.3119,-0.49095 0.3119,-1.58837 0,-1.16095 -0.27724,-1.62303 -0.27724,-0.46784 -0.80863,-0.46784 z" />
+ <path
+ id="path1102"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ d="m 106.56055,190.81325 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82595,-0.13862 0.38699,-0.13862 0.76242,-0.38699 l 0.63535,0.87216 q -0.42742,0.35811 -1.02233,0.57759 -0.58915,0.21949 -1.29958,0.21949 -0.99346,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02234,-1.13785 -0.34655,-0.72777 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.98191,-1.16096 0.6469,-0.43319 1.55371,-0.43319 1.25915,0 1.99846,0.82018 0.73932,0.82017 0.73932,2.26992 0,0.33501 -0.0289,0.60647 z m 1.31113,-2.62225 q -0.55449,0 -0.91259,0.39853 -0.35233,0.39854 -0.41587,1.2476 h 2.57605 q -0.0115,-0.77397 -0.31767,-1.20717 -0.30613,-0.43896 -0.92992,-0.43896 z" />
+ </g>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path2022"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m 175.57697,153.33338 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ id="text2026"
+ aria-label="element">
+ <path
+ id="path1079"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 186.26703,164.7701 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76241,-0.38699 l 0.63535,0.87216 q -0.42741,0.35811 -1.02233,0.57759 -0.58914,0.21949 -1.29958,0.21949 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34656,-0.72777 -0.34656,-1.67501 0,-0.9126 0.33501,-1.64613 0.34077,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55372,-0.43319 1.25914,0 1.99846,0.82017 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39854 -0.41586,1.2476 h 2.57605 q -0.0116,-0.77398 -0.31768,-1.20717 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1081"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 194.80957,158.8036 v 6.7809 q 0,0.39854 0.23681,0.56604 0.23681,0.1675 0.62957,0.1675 0.24837,0 0.4794,-0.052 0.23104,-0.0578 0.43897,-0.13862 l 0.37543,1.03966 q -0.28879,0.15017 -0.70466,0.25991 -0.41008,0.10975 -0.95302,0.10975 -0.99923,0 -1.51328,-0.57182 -0.51406,-0.57181 -0.51406,-1.54216 v -5.53909 h -1.83096 v -1.08009 z" />
+ <path
+ id="path1083"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 200.12915,164.7701 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38699 l 0.63534,0.87216 q -0.42741,0.35811 -1.02233,0.57759 -0.58914,0.21949 -1.29958,0.21949 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72777 -0.34655,-1.67501 0,-0.9126 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55372,-0.43319 1.25914,0 1.99846,0.82017 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39854 -0.41586,1.2476 h 2.57605 q -0.0116,-0.77398 -0.31768,-1.20717 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1085"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 210.10989,161.07353 q 0.57759,0 0.91259,0.38698 0.335,0.38121 0.335,1.36889 v 4.53408 h -1.32846 V 163.02 q 0,-0.41008 -0.0635,-0.58336 -0.0635,-0.17905 -0.30035,-0.17905 -0.1906,0 -0.38698,0.11551 -0.19638,0.10975 -0.39854,0.39854 v 4.59184 h -1.1494 V 163.02 q 0,-0.41008 -0.0635,-0.58336 -0.0635,-0.17905 -0.30034,-0.17905 -0.19061,0 -0.38699,0.11551 -0.19638,0.10975 -0.39854,0.39854 v 4.59184 h -1.34578 v -6.11668 h 1.13785 l 0.0982,0.63535 q 0.27147,-0.37543 0.57182,-0.58914 0.30034,-0.21948 0.72198,-0.21948 0.34656,0 0.61225,0.17327 0.27147,0.16751 0.38698,0.57759 0.26569,-0.335 0.58914,-0.54293 0.32923,-0.20793 0.75665,-0.20793 z" />
+ <path
+ id="path1087"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 213.99127,164.7701 q 0.0693,0.86061 0.50828,1.24182 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38699 l 0.63534,0.87216 q -0.42741,0.35811 -1.02233,0.57759 -0.58914,0.21949 -1.29958,0.21949 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72777 -0.34655,-1.67501 0,-0.9126 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55372,-0.43319 1.25914,0 1.99846,0.82017 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39854 -0.35233,0.39854 -0.41586,1.2476 H 216.55 q -0.0116,-0.77398 -0.31768,-1.20717 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ <path
+ id="path1089"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 219.62276,167.36348 v -6.11668 h 1.32845 l 0.10974,0.75665 q 0.7913,-0.92992 1.94071,-0.92992 0.82017,0 1.25337,0.4794 0.43896,0.47362 0.43896,1.33423 v 4.47632 h -1.52483 v -3.8814 q 0,-0.69311 -0.1444,-0.98191 -0.13862,-0.28879 -0.60069,-0.28879 -0.37544,0 -0.69889,0.23681 -0.32345,0.23681 -0.57759,0.57759 v 4.3377 z" />
+ <path
+ id="path1091"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ d="m 231.83299,167.0227 q -0.34078,0.22526 -0.82596,0.36966 -0.48517,0.1444 -1.05121,0.1444 -1.12052,0 -1.68656,-0.57759 -0.56604,-0.58337 -0.56604,-1.54794 v -3.08433 h -1.32846 v -1.0801 h 1.32846 v -1.34578 l 1.52484,-0.18483 v 1.53061 h 2.02156 l -0.15595,1.0801 h -1.86561 v 3.07855 q 0,0.47362 0.23103,0.69311 0.23104,0.21948 0.74509,0.21948 0.32923,0 0.6007,-0.0751 0.27724,-0.0809 0.5025,-0.20216 z" />
+ </g>
+ <path
+ d="M 55.175507,153.27835 H 170.22016 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 55.175507 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z"
+ style="opacity:0.25;fill:#d99b00;fill-opacity:1;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2031"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <g
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ id="text2035"
+ aria-label="dtype">
+ <path
+ id="path1068"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ d="m 99.886927,157.49231 1.524833,0.16172 v 8.55988 h -1.35156 l -0.09241,-0.72198 q -0.283019,0.40431 -0.710435,0.65267 -0.427416,0.24259 -0.993454,0.24259 -0.773971,0 -1.28225,-0.40431 -0.502503,-0.40432 -0.750866,-1.13208 -0.242588,-0.73354 -0.242588,-1.70389 0,-0.92992 0.288795,-1.65768 0.294571,-0.73354 0.837505,-1.1494 0.542934,-0.41587 1.293801,-0.41587 0.895264,0 1.47863,0.61802 z m -1.068541,3.5695 q -0.57759,0 -0.912592,0.50251 -0.329226,0.49672 -0.329226,1.58837 0,1.15518 0.306122,1.62302 0.306123,0.46785 0.825954,0.46785 0.381209,0 0.670004,-0.22526 0.288795,-0.23103 0.508279,-0.57181 v -2.78398 q -0.213708,-0.28302 -0.4794,-0.43897 -0.259915,-0.16173 -0.589141,-0.16173 z" />
+ <path
+ id="path1070"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ d="m 108.55076,165.87314 q -0.34078,0.22526 -0.82596,0.36965 -0.48517,0.1444 -1.05121,0.1444 -1.12052,0 -1.68656,-0.57759 -0.56604,-0.58337 -0.56604,-1.54794 v -3.08433 h -1.32846 v -1.08009 h 1.32846 v -1.34579 l 1.52484,-0.18482 v 1.53061 h 2.02156 l -0.15595,1.08009 h -1.86561 v 3.07855 q 0,0.47363 0.23103,0.69311 0.23104,0.21949 0.74509,0.21949 0.32923,0 0.6007,-0.0751 0.27724,-0.0809 0.5025,-0.20216 z" />
+ <path
+ id="path1072"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ d="m 115.74173,160.09724 -2.07355,6.12822 q -0.37543,1.12053 -1.11474,1.76743 -0.73932,0.65268 -2.06777,0.74509 l -0.19061,-1.1032 q 0.61225,-0.0866 0.9819,-0.25991 0.37544,-0.17328 0.59492,-0.4563 0.22526,-0.28302 0.38699,-0.70466 h -0.51983 l -2.00424,-6.11667 h 1.61147 l 1.38622,5.10012 1.44397,-5.10012 z" />
+ <path
+ id="path1074"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ d="m 120.29312,159.92396 q 0.80285,0 1.2938,0.39854 0.49095,0.39276 0.71044,1.12052 0.22526,0.72199 0.22526,1.69812 0,0.94147 -0.27147,1.67501 -0.27147,0.73353 -0.79707,1.15518 -0.51983,0.41586 -1.28225,0.41586 -0.9357,0 -1.51329,-0.66423 v 2.84752 l -1.52483,0.16172 v -8.63496 h 1.34 l 0.0809,0.74509 q 0.3581,-0.47362 0.80862,-0.69311 0.4563,-0.22526 0.92992,-0.22526 z m -0.44474,1.14363 q -0.38699,0 -0.68156,0.23103 -0.28879,0.23104 -0.50828,0.57182 v 2.73777 q 0.42164,0.6238 1.07432,0.6238 0.58337,0 0.88949,-0.48517 0.3119,-0.49096 0.3119,-1.58838 0,-1.16095 -0.27725,-1.62302 -0.27724,-0.46785 -0.80862,-0.46785 z" />
+ <path
+ id="path1076"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ d="m 125.36434,163.62054 q 0.0693,0.8606 0.50828,1.24181 0.43897,0.38121 1.06854,0.38121 0.43897,0 0.82596,-0.13862 0.38698,-0.13862 0.76242,-0.38698 l 0.63534,0.87216 q -0.42741,0.3581 -1.02233,0.57759 -0.58914,0.21948 -1.29958,0.21948 -0.99345,0 -1.67501,-0.41009 -0.67578,-0.41009 -1.02233,-1.13785 -0.34655,-0.72776 -0.34655,-1.67501 0,-0.91259 0.335,-1.64613 0.34078,-0.73354 0.9819,-1.16096 0.6469,-0.43319 1.55372,-0.43319 1.25914,0 1.99846,0.82018 0.73931,0.82018 0.73931,2.26993 0,0.335 -0.0289,0.60647 z m 1.31113,-2.62226 q -0.55448,0 -0.91259,0.39853 -0.35233,0.39854 -0.41586,1.2476 h 2.57605 q -0.0116,-0.77397 -0.31768,-1.20716 -0.30612,-0.43897 -0.92992,-0.43897 z" />
+ </g>
+ <path
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 52.572927,70.114137 V 205.33633"
+ id="path3042"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text3050"
+ aria-label="Python type">
+ <path
+ id="path1047"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -121.47364,105.10011 h 2.42156 q 1.08004,0 1.65606,0.48128 0.57981,0.47749 0.57981,1.36426 0,0.89055 -0.57981,1.37183 -0.57602,0.47749 -1.65606,0.47749 h -0.96256 v 1.96302 h -1.459 z m 1.459,1.0573 v 1.58026 h 0.80719 q 0.42443,0 0.6556,-0.20464 0.23117,-0.20842 0.23117,-0.58738 0,-0.37896 -0.23117,-0.5836 -0.23117,-0.20464 -0.6556,-0.20464 z" />
+ <path
+ id="path1049"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -116.25914,106.51363 h 1.35668 l 1.14067,2.8801 0.97014,-2.8801 h 1.35668 l -1.78491,4.64606 q -0.26906,0.70865 -0.62907,0.98908 -0.35622,0.28422 -0.94361,0.28422 h -0.78445 v -0.89055 h 0.42443 q 0.34486,0 0.50023,-0.1099 0.15917,-0.1099 0.24633,-0.39412 l 0.0379,-0.11748 z" />
+ <path
+ id="path1051"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -109.16121,105.30854 v 1.20509 h 1.39836 v 0.97014 h -1.39836 v 1.80006 q 0,0.29559 0.11748,0.4017 0.11747,0.10232 0.46612,0.10232 h 0.69729 v 0.97014 h -1.16341 q -0.8034,0 -1.14067,-0.33349 -0.33349,-0.33727 -0.33349,-1.14067 v -1.80006 h -0.67455 v -0.97014 h 0.67455 v -1.20509 z" />
+ <path
+ id="path1053"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -102.66583,108.17348 v 2.58451 h -1.36426 v -0.42065 -1.54995 q 0,-0.55707 -0.0265,-0.7655 -0.0227,-0.20842 -0.0834,-0.30695 -0.0796,-0.13264 -0.21601,-0.20464 -0.13643,-0.0758 -0.31075,-0.0758 -0.42444,0 -0.66697,0.3297 -0.24253,0.32591 -0.24253,0.90572 v 2.08807 h -1.35668 v -5.89663 h 1.35668 v 2.27377 q 0.30695,-0.37139 0.65181,-0.54571 0.34485,-0.17811 0.76171,-0.17811 0.73518,0 1.11414,0.45096 0.38275,0.45097 0.38275,1.31121 z" />
+ <path
+ id="path1055"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -99.387821,107.38145 q -0.450963,0 -0.689709,0.32591 -0.23495,0.32211 -0.23495,0.93224 0,0.61013 0.23495,0.93603 0.238746,0.32212 0.689709,0.32212 0.443384,0 0.678339,-0.32212 0.234956,-0.3259 0.234956,-0.93603 0,-0.61013 -0.234956,-0.93224 -0.234955,-0.32591 -0.678339,-0.32591 z m 0,-0.97014 q 1.095196,0 1.709112,0.59118 0.617705,0.59118 0.617705,1.63711 0,1.04593 -0.617705,1.63711 -0.613916,0.59118 -1.709112,0.59118 -1.098989,0 -1.720479,-0.59118 -0.61771,-0.59118 -0.61771,-1.63711 0,-1.04593 0.61771,-1.63711 0.62149,-0.59118 1.720479,-0.59118 z" />
+ <path
+ id="path1057"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -91.808612,108.17348 v 2.58451 h -1.364257 v -0.42065 -1.55753 q 0,-0.54949 -0.02653,-0.75792 -0.02274,-0.20842 -0.08337,-0.30695 -0.07958,-0.13264 -0.216007,-0.20464 -0.136426,-0.0758 -0.310748,-0.0758 -0.424435,0 -0.66697,0.3297 -0.242535,0.32591 -0.242535,0.90572 v 2.08807 h -1.356678 v -4.24436 h 1.356678 v 0.6215 q 0.306958,-0.37139 0.651812,-0.54571 0.344854,-0.17811 0.761711,-0.17811 0.735183,0 1.114143,0.45096 0.38275,0.45097 0.38275,1.31121 z" />
+ <path
+ id="path1059"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -86.366739,105.30854 v 1.20509 h 1.398364 v 0.97014 h -1.398364 v 1.80006 q 0,0.29559 0.117478,0.4017 0.117478,0.10232 0.466121,0.10232 h 0.697287 v 0.97014 h -1.163408 q -0.803396,0 -1.140671,-0.33349 -0.333485,-0.33727 -0.333485,-1.14067 v -1.80006 h -0.67455 v -0.97014 h 0.67455 v -1.20509 z" />
+ <path
+ id="path1061"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -84.695524,106.51363 h 1.356678 l 1.140671,2.8801 0.970139,-2.8801 h 1.356678 l -1.784903,4.64606 q -0.269062,0.70865 -0.629075,0.98908 -0.356222,0.28422 -0.943611,0.28422 h -0.784448 v -0.89055 h 0.424435 q 0.344854,0 0.500228,-0.1099 0.159164,-0.1099 0.246325,-0.39412 l 0.0379,-0.11748 z" />
+ <path
+ id="path1063"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -77.722654,110.14407 v 2.22829 h -1.356678 v -5.85873 h 1.356678 v 0.6215 q 0.280431,-0.37139 0.621496,-0.54571 0.341064,-0.17811 0.784448,-0.17811 0.784448,0 1.288465,0.62529 0.504018,0.62149 0.504018,1.603 0,0.98151 -0.504018,1.60679 -0.504017,0.6215 -1.288465,0.6215 -0.443384,0 -0.784448,-0.17433 -0.341065,-0.17811 -0.621496,-0.54949 z m 0.901926,-2.74746 q -0.435804,0 -0.67076,0.32212 -0.231166,0.31832 -0.231166,0.92087 0,0.60255 0.231166,0.92466 0.234956,0.31833 0.67076,0.31833 0.435805,0 0.663181,-0.31833 0.231166,-0.31832 0.231166,-0.92466 0,-0.60634 -0.231166,-0.92466 -0.227376,-0.31833 -0.663181,-0.31833 z" />
+ <path
+ id="path1065"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -69.286993,108.62444 v 0.38654 h -3.171899 q 0.04927,0.47749 0.344854,0.71624 0.295589,0.23874 0.826134,0.23874 0.428225,0 0.875398,-0.12506 0.450963,-0.12884 0.924664,-0.38654 v 1.04593 q -0.48128,0.18191 -0.96256,0.27286 -0.48128,0.0947 -0.962559,0.0947 -1.15204,0 -1.792483,-0.5836 -0.636654,-0.58739 -0.636654,-1.64469 0,-1.03835 0.625285,-1.63332 0.629074,-0.59497 1.72806,-0.59497 1.000455,0 1.599213,0.60255 0.602547,0.60255 0.602547,1.61058 z m -1.394575,-0.45096 q 0,-0.38654 -0.227376,-0.6215 -0.223587,-0.23874 -0.587389,-0.23874 -0.394118,0 -0.640443,0.22358 -0.246324,0.2198 -0.306958,0.63666 z" />
+ </g>
+ <g
+ style="font-size:3.52778px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect3054)"
+ id="text3052" />
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text3062"
+ aria-label="Python type
+with ABC">
+ <path
+ id="path1011"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -121.47364,128.2522 h 2.42156 q 1.08004,0 1.65606,0.48128 0.57981,0.47749 0.57981,1.36426 0,0.89055 -0.57981,1.37183 -0.57602,0.47749 -1.65606,0.47749 h -0.96256 v 1.96302 h -1.459 z m 1.459,1.0573 v 1.58027 h 0.80719 q 0.42443,0 0.6556,-0.20464 0.23117,-0.20843 0.23117,-0.58739 0,-0.37896 -0.23117,-0.5836 -0.23117,-0.20464 -0.6556,-0.20464 z" />
+ <path
+ id="path1013"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -116.25914,129.66572 h 1.35668 l 1.14067,2.8801 0.97014,-2.8801 h 1.35668 l -1.78491,4.64606 q -0.26906,0.70865 -0.62907,0.98908 -0.35622,0.28423 -0.94361,0.28423 h -0.78445 v -0.89056 h 0.42443 q 0.34486,0 0.50023,-0.1099 0.15917,-0.1099 0.24633,-0.39412 l 0.0379,-0.11748 z" />
+ <path
+ id="path1015"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -109.16121,128.46063 v 1.20509 h 1.39836 v 0.97014 h -1.39836 v 1.80006 q 0,0.29559 0.11748,0.4017 0.11747,0.10232 0.46612,0.10232 h 0.69729 v 0.97014 h -1.16341 q -0.8034,0 -1.14067,-0.33349 -0.33349,-0.33727 -0.33349,-1.14067 v -1.80006 h -0.67455 v -0.97014 h 0.67455 v -1.20509 z" />
+ <path
+ id="path1017"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -102.66583,131.32557 v 2.58451 h -1.36426 v -0.42065 -1.54994 q 0,-0.55708 -0.0265,-0.7655 -0.0227,-0.20843 -0.0834,-0.30696 -0.0796,-0.13264 -0.21601,-0.20464 -0.13643,-0.0758 -0.31075,-0.0758 -0.42444,0 -0.66697,0.32969 -0.24253,0.32591 -0.24253,0.90572 v 2.08807 h -1.35668 v -5.89662 h 1.35668 v 2.27376 q 0.30695,-0.37138 0.65181,-0.5457 0.34485,-0.17812 0.76171,-0.17812 0.73518,0 1.11414,0.45097 0.38275,0.45096 0.38275,1.3112 z" />
+ <path
+ id="path1019"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -99.387821,130.53354 q -0.450963,0 -0.689709,0.32591 -0.23495,0.32211 -0.23495,0.93224 0,0.61013 0.23495,0.93603 0.238746,0.32212 0.689709,0.32212 0.443384,0 0.678339,-0.32212 0.234956,-0.3259 0.234956,-0.93603 0,-0.61013 -0.234956,-0.93224 -0.234955,-0.32591 -0.678339,-0.32591 z m 0,-0.97014 q 1.095196,0 1.709112,0.59118 0.617705,0.59118 0.617705,1.63711 0,1.04593 -0.617705,1.63711 -0.613916,0.59118 -1.709112,0.59118 -1.098989,0 -1.720479,-0.59118 -0.61771,-0.59118 -0.61771,-1.63711 0,-1.04593 0.61771,-1.63711 0.62149,-0.59118 1.720479,-0.59118 z" />
+ <path
+ id="path1021"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -91.808612,131.32557 v 2.58451 h -1.364257 v -0.42065 -1.55752 q 0,-0.5495 -0.02653,-0.75792 -0.02274,-0.20843 -0.08337,-0.30696 -0.07958,-0.13264 -0.216007,-0.20464 -0.136426,-0.0758 -0.310748,-0.0758 -0.424435,0 -0.66697,0.32969 -0.242535,0.32591 -0.242535,0.90572 v 2.08807 h -1.356678 v -4.24436 h 1.356678 v 0.6215 q 0.306958,-0.37138 0.651812,-0.5457 0.344854,-0.17812 0.761711,-0.17812 0.735183,0 1.114143,0.45097 0.38275,0.45096 0.38275,1.3112 z" />
+ <path
+ id="path1023"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -86.366739,128.46063 v 1.20509 h 1.398364 v 0.97014 h -1.398364 v 1.80006 q 0,0.29559 0.117478,0.4017 0.117478,0.10232 0.466121,0.10232 h 0.697287 v 0.97014 h -1.163408 q -0.803396,0 -1.140671,-0.33349 -0.333485,-0.33727 -0.333485,-1.14067 v -1.80006 h -0.67455 v -0.97014 h 0.67455 v -1.20509 z" />
+ <path
+ id="path1025"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -84.695524,129.66572 h 1.356678 l 1.140671,2.8801 0.970139,-2.8801 h 1.356678 l -1.784903,4.64606 q -0.269062,0.70865 -0.629075,0.98908 -0.356222,0.28423 -0.943611,0.28423 h -0.784448 v -0.89056 h 0.424435 q 0.344854,0 0.500228,-0.1099 0.159164,-0.1099 0.246325,-0.39412 l 0.0379,-0.11748 z" />
+ <path
+ id="path1027"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -77.722654,133.29616 v 2.22829 h -1.356678 v -5.85873 h 1.356678 v 0.6215 q 0.280431,-0.37138 0.621496,-0.5457 0.341064,-0.17812 0.784448,-0.17812 0.784448,0 1.288465,0.62529 0.504018,0.62149 0.504018,1.603 0,0.98151 -0.504018,1.60679 -0.504017,0.6215 -1.288465,0.6215 -0.443384,0 -0.784448,-0.17432 -0.341065,-0.17811 -0.621496,-0.5495 z m 0.901926,-2.74746 q -0.435804,0 -0.67076,0.32212 -0.231166,0.31832 -0.231166,0.92087 0,0.60255 0.231166,0.92466 0.234956,0.31833 0.67076,0.31833 0.435805,0 0.663181,-0.31833 0.231166,-0.31832 0.231166,-0.92466 0,-0.60634 -0.231166,-0.92466 -0.227376,-0.31833 -0.663181,-0.31833 z" />
+ <path
+ id="path1029"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -69.286993,131.77653 v 0.38654 h -3.171899 q 0.04927,0.47749 0.344854,0.71624 0.295589,0.23874 0.826134,0.23874 0.428225,0 0.875398,-0.12505 0.450963,-0.12885 0.924664,-0.38654 v 1.04593 q -0.48128,0.1819 -0.96256,0.27285 -0.48128,0.0947 -0.962559,0.0947 -1.15204,0 -1.792483,-0.5836 -0.636654,-0.58739 -0.636654,-1.64469 0,-1.03835 0.625285,-1.63332 0.629074,-0.59497 1.72806,-0.59497 1.000455,0 1.599213,0.60255 0.602547,0.60255 0.602547,1.61058 z m -1.394575,-0.45096 q 0,-0.38654 -0.227376,-0.6215 -0.223587,-0.23874 -0.587389,-0.23874 -0.394118,0 -0.640443,0.22359 -0.246324,0.21979 -0.306958,0.63665 z" />
+ <path
+ id="path1031"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -121.91323,139.36711 h 1.31878 l 0.71245,2.92557 0.71623,-2.92557 h 1.1331 l 0.71244,2.89526 0.71624,-2.89526 h 1.31878 l -1.11793,4.24436 h -1.48174 l -0.71624,-2.918 -0.71244,2.918 h -1.48174 z" />
+ <path
+ id="path1033"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -114.36434,139.36711 h 1.35668 v 4.24436 h -1.35668 z m 0,-1.65227 h 1.35668 v 1.10657 h -1.35668 z" />
+ <path
+ id="path1035"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -110.2223,138.16202 v 1.20509 h 1.39836 v 0.97014 h -1.39836 v 1.80006 q 0,0.29559 0.11748,0.4017 0.11748,0.10232 0.46612,0.10232 h 0.69729 v 0.97014 h -1.16341 q -0.8034,0 -1.14067,-0.33349 -0.33349,-0.33727 -0.33349,-1.14067 v -1.80006 h -0.67455 v -0.97014 h 0.67455 v -1.20509 z" />
+ <path
+ id="path1037"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -103.72692,141.02696 v 2.58451 h -1.36426 v -0.42065 -1.54995 q 0,-0.55707 -0.0265,-0.7655 -0.0227,-0.20843 -0.0834,-0.30696 -0.0796,-0.13263 -0.21601,-0.20463 -0.13643,-0.0758 -0.31075,-0.0758 -0.42443,0 -0.66697,0.3297 -0.24253,0.32591 -0.24253,0.90572 v 2.08807 h -1.35668 v -5.89663 h 1.35668 v 2.27377 q 0.30695,-0.37139 0.65181,-0.54571 0.34485,-0.17811 0.76171,-0.17811 0.73518,0 1.11414,0.45096 0.38275,0.45097 0.38275,1.31121 z" />
+ <path
+ id="path1039"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -96.272765,142.58069 h -2.281342 l -0.360013,1.03078 h -1.46658 l 2.095655,-5.65788 h 1.739428 l 2.095651,5.65788 h -1.466576 z m -1.91754,-1.04972 h 1.549948 l -0.773079,-2.25102 z" />
+ <path
+ id="path1041"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -91.43344,140.14398 q 0.344854,0 0.522965,-0.15158 0.178112,-0.15159 0.178112,-0.44718 0,-0.2918 -0.178112,-0.44338 -0.178111,-0.15538 -0.522965,-0.15538 h -0.807186 v 1.19752 z m 0.04927,2.47461 q 0.439594,0 0.659391,-0.18569 0.223586,-0.18569 0.223586,-0.56086 0,-0.36759 -0.219797,-0.54949 -0.219797,-0.18569 -0.66318,-0.18569 h -0.856451 v 1.48173 z m 1.356678,-2.03502 q 0.469911,0.13643 0.727604,0.50402 0.257693,0.36759 0.257693,0.90193 0,0.81855 -0.553282,1.22025 -0.553282,0.4017 -1.682584,0.4017 h -2.421558 v -5.65788 h 2.190392 q 1.178567,0 1.705322,0.35622 0.530544,0.35622 0.530544,1.14067 0,0.41307 -0.19327,0.70487 -0.193269,0.28801 -0.560861,0.42822 z" />
+ <path
+ id="path1043"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -83.297161,143.30072 q -0.401698,0.20843 -0.837502,0.31454 -0.435805,0.10611 -0.909505,0.10611 -1.413523,0 -2.239657,-0.78824 -0.826133,-0.79203 -0.826133,-2.14492 0,-1.35668 0.826133,-2.14491 0.826134,-0.79203 2.239657,-0.79203 0.4737,0 0.909505,0.10611 0.435804,0.10611 0.837502,0.31453 v 1.17099 q -0.405488,-0.27664 -0.799606,-0.40549 -0.394119,-0.12884 -0.829924,-0.12884 -0.780658,0 -1.227832,0.50023 -0.447173,0.50022 -0.447173,1.37941 0,0.8754 0.447173,1.37563 0.447174,0.50023 1.227832,0.50023 0.435805,0 0.829924,-0.12885 0.394118,-0.12885 0.799606,-0.40549 z" />
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text3070"
+ aria-label="NEP 41 Proposal">
+ <path
+ id="path984"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -139.86458,159.57088 h 1.62953 l 2.05775,3.88056 v -3.88056 h 1.38321 v 5.65788 h -1.62953 l -2.05776,-3.88056 v 3.88056 h -1.3832 z" />
+ <path
+ id="path986"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -133.3692,159.57088 h 3.9374 v 1.10278 h -2.4784 v 1.05351 h 2.33061 v 1.10277 h -2.33061 v 1.29604 h 2.56177 v 1.10278 h -4.02077 z" />
+ <path
+ id="path988"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -128.06754,159.57088 h 2.42156 q 1.08003,0 1.65605,0.48128 0.57981,0.47749 0.57981,1.36426 0,0.89055 -0.57981,1.37183 -0.57602,0.47749 -1.65605,0.47749 h -0.96256 v 1.96302 h -1.459 z m 1.459,1.0573 v 1.58027 h 0.80718 q 0.42444,0 0.6556,-0.20464 0.23117,-0.20843 0.23117,-0.58739 0,-0.37896 -0.23117,-0.5836 -0.23116,-0.20464 -0.6556,-0.20464 z" />
+ <path
+ id="path990"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -117.53244,160.77218 -1.59921,2.36851 h 1.59921 z m -0.24254,-1.2013 h 1.62195 v 3.56981 h 0.80719 v 1.0573 h -0.80719 v 1.03077 h -1.37941 v -1.03077 h -2.50872 v -1.25057 z" />
+ <path
+ id="path992"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -114.08011,164.22072 h 1.28846 v -3.65696 l -1.32257,0.27285 v -0.99288 l 1.31499,-0.27285 h 1.387 v 4.64984 h 1.28846 v 1.00804 h -3.95634 z" />
+ <path
+ id="path994"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -106.175,159.57088 h 2.42156 q 1.08004,0 1.65606,0.48128 0.57981,0.47749 0.57981,1.36426 0,0.89055 -0.57981,1.37183 -0.57602,0.47749 -1.65606,0.47749 h -0.96256 v 1.96302 h -1.459 z m 1.459,1.0573 v 1.58027 h 0.80719 q 0.42443,0 0.6556,-0.20464 0.23116,-0.20843 0.23116,-0.58739 0,-0.37896 -0.23116,-0.5836 -0.23117,-0.20464 -0.6556,-0.20464 z" />
+ <path
+ id="path996"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -97.394486,162.14023 q -0.178112,-0.0834 -0.356223,-0.12127 -0.174322,-0.0417 -0.352433,-0.0417 -0.522966,0 -0.807186,0.33727 -0.280431,0.33349 -0.280431,0.95877 v 1.95544 h -1.356681 v -4.24436 h 1.356681 v 0.69729 q 0.261483,-0.41686 0.598758,-0.60634 0.341064,-0.19327 0.814765,-0.19327 0.06821,0 0.147794,0.008 0.07958,0.004 0.231166,0.0227 z" />
+ <path
+ id="path998"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -94.700075,161.85222 q -0.450963,0 -0.689708,0.32591 -0.234955,0.32211 -0.234955,0.93224 0,0.61013 0.234955,0.93603 0.238745,0.32212 0.689708,0.32212 0.443384,0 0.678339,-0.32212 0.234956,-0.3259 0.234956,-0.93603 0,-0.61013 -0.234956,-0.93224 -0.234955,-0.32591 -0.678339,-0.32591 z m 0,-0.97014 q 1.095196,0 1.709112,0.59118 0.617705,0.59118 0.617705,1.63711 0,1.04593 -0.617705,1.63711 -0.613916,0.59118 -1.709112,0.59118 -1.098985,0 -1.72048,-0.59118 -0.617706,-0.59118 -0.617706,-1.63711 0,-1.04593 0.617706,-1.63711 0.621495,-0.59118 1.72048,-0.59118 z" />
+ <path
+ id="path1000"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -90.031282,164.61484 v 2.22829 h -1.356678 v -5.85873 h 1.356678 v 0.6215 q 0.280431,-0.37138 0.621495,-0.54571 0.341065,-0.17811 0.784449,-0.17811 0.784448,0 1.288465,0.62529 0.504017,0.62149 0.504017,1.603 0,0.98151 -0.504017,1.60679 -0.504017,0.6215 -1.288465,0.6215 -0.443384,0 -0.784449,-0.17432 -0.341064,-0.17811 -0.621495,-0.5495 z m 0.901926,-2.74746 q -0.435804,0 -0.67076,0.32212 -0.231166,0.31832 -0.231166,0.92087 0,0.60255 0.231166,0.92466 0.234956,0.31833 0.67076,0.31833 0.435805,0 0.663181,-0.31833 0.231166,-0.31832 0.231166,-0.92466 0,-0.60634 -0.231166,-0.92466 -0.227376,-0.31833 -0.663181,-0.31833 z" />
+ <path
+ id="path1002"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -83.812544,161.85222 q -0.450963,0 -0.689708,0.32591 -0.234955,0.32211 -0.234955,0.93224 0,0.61013 0.234955,0.93603 0.238745,0.32212 0.689708,0.32212 0.443384,0 0.67834,-0.32212 0.234955,-0.3259 0.234955,-0.93603 0,-0.61013 -0.234955,-0.93224 -0.234956,-0.32591 -0.67834,-0.32591 z m 0,-0.97014 q 1.095196,0 1.709112,0.59118 0.617705,0.59118 0.617705,1.63711 0,1.04593 -0.617705,1.63711 -0.613916,0.59118 -1.709112,0.59118 -1.098985,0 -1.72048,-0.59118 -0.617706,-0.59118 -0.617706,-1.63711 0,-1.04593 0.617706,-1.63711 0.621495,-0.59118 1.72048,-0.59118 z" />
+ <path
+ id="path1004"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -77.184525,161.11704 v 1.03077 q -0.435804,-0.1819 -0.841292,-0.27285 -0.405488,-0.0909 -0.7655,-0.0909 -0.38654,0 -0.57602,0.0985 -0.185691,0.0947 -0.185691,0.29559 0,0.16295 0.140216,0.25011 0.144005,0.0872 0.511596,0.12885 l 0.238745,0.0341 q 1.042142,0.13263 1.402154,0.4358 0.360012,0.30317 0.360012,0.95119 0,0.67834 -0.500227,1.0194 -0.500228,0.34107 -1.493105,0.34107 -0.420646,0 -0.871609,-0.0682 -0.447173,-0.0644 -0.920873,-0.19706 v -1.03078 q 0.405487,0.19706 0.829923,0.29559 0.428225,0.0985 0.867819,0.0985 0.397909,0 0.598758,-0.1099 0.200849,-0.10989 0.200849,-0.3259 0,-0.1819 -0.140215,-0.26906 -0.136426,-0.0909 -0.549493,-0.14022 l -0.238745,-0.0303 q -0.905716,-0.11368 -1.269518,-0.42064 -0.363802,-0.30696 -0.363802,-0.93224 0,-0.67455 0.462332,-1.00046 0.462332,-0.32591 1.417312,-0.32591 0.375171,0 0.788238,0.0568 0.413067,0.0568 0.898136,0.17811 z" />
+ <path
+ id="path1006"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -73.978521,163.3188 q -0.424436,0 -0.640444,0.144 -0.212217,0.14401 -0.212217,0.42444 0,0.25769 0.170532,0.40549 0.174322,0.144 0.481279,0.144 0.382751,0 0.644233,-0.27285 0.261483,-0.27664 0.261483,-0.68971 v -0.15537 z m 2.072913,-0.5116 v 2.42156 h -1.368047 v -0.62907 q -0.272852,0.38654 -0.613916,0.56465 -0.341064,0.17432 -0.829923,0.17432 -0.659391,0 -1.072458,-0.38275 -0.409278,-0.38654 -0.409278,-1.00046 0,-0.74655 0.511597,-1.09519 0.515386,-0.34865 1.614371,-0.34865 h 0.799607 v -0.10611 q 0,-0.32211 -0.253904,-0.46991 -0.253903,-0.15158 -0.792027,-0.15158 -0.435804,0 -0.810975,0.0872 -0.375171,0.0872 -0.697287,0.26148 v -1.03456 q 0.435804,-0.10611 0.875398,-0.15916 0.439594,-0.0568 0.879188,-0.0568 1.148251,0 1.656058,0.45476 0.511596,0.45096 0.511596,1.47036 z" />
+ <path
+ id="path1008"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -70.643667,159.33214 h 1.356679 v 5.89662 h -1.356679 z" />
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ id="text3076"
+ aria-label="Alternative">
+ <path
+ id="path961"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -113.68979,192.17046 h -2.28134 l -0.36001,1.03077 h -1.46658 l 2.09565,-5.65788 h 1.73943 l 2.09565,5.65788 h -1.46658 z m -1.91754,-1.04972 h 1.54995 l -0.77308,-2.25102 z" />
+ <path
+ id="path963"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -111.17728,187.30461 h 1.35668 v 5.89662 h -1.35668 z" />
+ <path
+ id="path965"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -107.03524,187.75178 v 1.2051 h 1.39836 v 0.97013 h -1.39836 v 1.80007 q 0,0.29559 0.11747,0.40169 0.11748,0.10232 0.46612,0.10232 h 0.69729 v 0.97014 h -1.16341 q -0.80339,0 -1.14067,-0.33348 -0.33348,-0.33728 -0.33348,-1.14067 v -1.80007 h -0.67455 v -0.97013 h 0.67455 v -1.2051 z" />
+ <path
+ id="path967"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -100.57018,191.06769 v 0.38654 h -3.1719 q 0.0493,0.47749 0.34486,0.71623 0.29559,0.23875 0.82613,0.23875 0.42823,0 0.8754,-0.12506 0.45096,-0.12885 0.92466,-0.38654 v 1.04593 q -0.48128,0.1819 -0.96256,0.27285 -0.48128,0.0947 -0.96256,0.0947 -1.15204,0 -1.79248,-0.5836 -0.63665,-0.58739 -0.63665,-1.64469 0,-1.03835 0.62528,-1.63332 0.62908,-0.59496 1.72806,-0.59496 1.00046,0 1.59921,0.60254 0.60255,0.60255 0.60255,1.61059 z m -1.39457,-0.45097 q 0,-0.38654 -0.22738,-0.62149 -0.22359,-0.23875 -0.58739,-0.23875 -0.39412,0 -0.64044,0.22359 -0.24633,0.2198 -0.30696,0.63665 z" />
+ <path
+ id="path969"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -96.390244,190.11271 q -0.178112,-0.0834 -0.356223,-0.12127 -0.174322,-0.0417 -0.352434,-0.0417 -0.522965,0 -0.807185,0.33728 -0.280431,0.33348 -0.280431,0.95877 v 1.95543 h -1.356678 v -4.24435 h 1.356678 v 0.69728 q 0.261483,-0.41685 0.598758,-0.60633 0.341064,-0.19327 0.814764,-0.19327 0.06821,0 0.147795,0.008 0.07958,0.004 0.231166,0.0227 z" />
+ <path
+ id="path971"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -91.448601,190.61672 v 2.58451 h -1.364258 v -0.42064 -1.55753 q 0,-0.54949 -0.02653,-0.75792 -0.02274,-0.20843 -0.08337,-0.30696 -0.07958,-0.13264 -0.216007,-0.20464 -0.136426,-0.0758 -0.310748,-0.0758 -0.424435,0 -0.66697,0.3297 -0.242535,0.3259 -0.242535,0.90571 v 2.08807 h -1.356678 v -4.24435 h 1.356678 v 0.62149 q 0.306958,-0.37138 0.651812,-0.5457 0.344854,-0.17811 0.761711,-0.17811 0.735183,0 1.114144,0.45096 0.38275,0.45096 0.38275,1.3112 z" />
+ <path
+ id="path973"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -88.288071,191.29127 q -0.424435,0 -0.640443,0.14401 -0.212218,0.144 -0.212218,0.42443 0,0.2577 0.170532,0.40549 0.174322,0.14401 0.48128,0.14401 0.38275,0 0.644233,-0.27286 0.261483,-0.27664 0.261483,-0.6897 v -0.15538 z m 2.072914,-0.51159 v 2.42155 h -1.368047 v -0.62907 q -0.272852,0.38654 -0.613916,0.56465 -0.341065,0.17432 -0.829924,0.17432 -0.659391,0 -1.072458,-0.38275 -0.409277,-0.38654 -0.409277,-1.00045 0,-0.74656 0.511597,-1.0952 0.515386,-0.34864 1.614371,-0.34864 h 0.799607 v -0.10611 q 0,-0.32212 -0.253904,-0.46991 -0.253903,-0.15159 -0.792027,-0.15159 -0.435805,0 -0.810976,0.0872 -0.37517,0.0872 -0.697287,0.26149 v -1.03457 q 0.435805,-0.1061 0.875399,-0.15916 0.439594,-0.0568 0.879188,-0.0568 1.14825,0 1.656057,0.45475 0.511597,0.45096 0.511597,1.47037 z" />
+ <path
+ id="path975"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -83.471483,187.75178 v 1.2051 h 1.398364 v 0.97013 h -1.398364 v 1.80007 q 0,0.29559 0.117478,0.40169 0.117478,0.10232 0.466121,0.10232 h 0.697288 v 0.97014 h -1.163409 q -0.803396,0 -1.140671,-0.33348 -0.333485,-0.33728 -0.333485,-1.14067 v -1.80007 h -0.67455 v -0.97013 h 0.67455 v -1.2051 z" />
+ <path
+ id="path977"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -81.243196,188.95688 h 1.356678 v 4.24435 h -1.356678 z m 0,-1.65227 h 1.356678 v 1.10656 h -1.356678 z" />
+ <path
+ id="path979"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -79.117229,188.95688 h 1.356678 l 1.0573,2.93315 1.05351,-2.93315 h 1.360468 l -1.671216,4.24435 h -1.489314 z" />
+ <path
+ id="path981"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ d="m -69.286993,191.06769 v 0.38654 h -3.171899 q 0.04927,0.47749 0.344854,0.71623 0.295589,0.23875 0.826134,0.23875 0.428225,0 0.875398,-0.12506 0.450963,-0.12885 0.924664,-0.38654 v 1.04593 q -0.48128,0.1819 -0.96256,0.27285 -0.48128,0.0947 -0.962559,0.0947 -1.15204,0 -1.792483,-0.5836 -0.636654,-0.58739 -0.636654,-1.64469 0,-1.03835 0.625285,-1.63332 0.629074,-0.59496 1.72806,-0.59496 1.000455,0 1.599213,0.60254 0.602547,0.60255 0.602547,1.61059 z m -1.394575,-0.45097 q 0,-0.38654 -0.227376,-0.62149 -0.223587,-0.23875 -0.587389,-0.23875 -0.394118,0 -0.640443,0.22359 -0.246324,0.2198 -0.306958,0.63665 z" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path960"
+ d="M 244.3569,149.56007 H -141.19857"
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/doc/neps/_static/nep-0041-type-sketch.svg b/doc/neps/_static/nep-0041-type-sketch.svg
new file mode 100644
index 000000000..9e597db9d
--- /dev/null
+++ b/doc/neps/_static/nep-0041-type-sketch.svg
@@ -0,0 +1,523 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"
+ sodipodi:docname="nep-0041-type-sketch.svg"
+ id="svg8"
+ version="1.1"
+ viewBox="0 0 390.05549 139.7222"
+ height="139.7222mm"
+ width="390.05548mm">
+ <defs
+ id="defs2">
+ <rect
+ x="-108.43283"
+ y="116.0488"
+ width="38.824516"
+ height="5.9122801"
+ id="rect3054" />
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker7096"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#00b200;fill-opacity:1;fill-rule:evenodd;stroke:#00b200;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path7094"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker5628"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#000081;fill-opacity:1;fill-rule:evenodd;stroke:#000081;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path5626"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker5618"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Sstart">
+ <path
+ transform="matrix(0.2,0,0,0.2,1.2,0)"
+ style="fill:#000081;fill-opacity:1;fill-rule:evenodd;stroke:#000081;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path5616"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker4826"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#206120;fill-opacity:1;fill-rule:evenodd;stroke:#206120;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4824"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker4400"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4398"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#00b200;fill-opacity:1;fill-rule:evenodd;stroke:#00b200;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker4390"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#b7943d;fill-opacity:1;fill-rule:evenodd;stroke:#b7943d;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4388"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="marker2037"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill:#f4ae00;fill-opacity:1;fill-rule:evenodd;stroke:#ffc433;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path2035"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <rect
+ id="rect1296"
+ height="8.8755655"
+ width="16.467854"
+ y="100.87298"
+ x="-2.9674385" />
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow1Lend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lend">
+ <path
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path915"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow1Lstart"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstart">
+ <path
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path912"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ inkscape:guide-bbox="true"
+ showguides="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="27"
+ inkscape:window-x="0"
+ inkscape:window-height="1376"
+ inkscape:window-width="2560"
+ showgrid="false"
+ inkscape:document-rotation="0"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="mm"
+ inkscape:cy="290.82008"
+ inkscape:cx="134.87089"
+ inkscape:zoom="0.98994949"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ lock-margins="true"
+ fit-margin-top="2"
+ fit-margin-left="2"
+ fit-margin-right="2"
+ fit-margin-bottom="2"
+ objecttolerance="29.7"
+ gridtolerance="20.4"
+ guidetolerance="19.1"
+ inkscape:snap-perpendicular="true"
+ inkscape:snap-tangential="true" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ transform="translate(143.44857,-67.864137)">
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1976"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m 175.57699,126.11316 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3044"
+ d="M 172.89254,70.114137 V 205.33633"
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 55.143494,98.892926 H 240.95778 c 1.14406,0 2.06509,0.921034 2.06509,2.065094 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 55.143494 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.065094 2.06509,-2.065094 z"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796609;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="rect5208"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <path
+ d="M -60.569299,98.727824 H 50.002364 c 1.14406,0 2.06509,0.92103 2.06509,2.065086 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H -60.569299 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.144056 0.92103,-2.065086 2.06509,-2.065086 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="rect4618"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <g
+ style="font-size:6.7452px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.505891"
+ id="text4368" />
+ <g
+ style="font-size:3.52778px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1296)"
+ id="text1294" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.76111px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ x="177.69284"
+ y="88.415688"
+ id="text1931"><tspan
+ sodipodi:role="line"
+ id="tspan1929"
+ x="177.69284"
+ y="88.415688"
+ style="fill:#000000;stroke-width:0.105503">Value Storage</tspan></text>
+ <text
+ id="text1935"
+ y="78.750557"
+ x="77.626938"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.76111px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ xml:space="preserve"><tspan
+ style="fill:#000000;stroke-width:0.105503"
+ y="78.750557"
+ x="77.626938"
+ id="tspan1933"
+ sodipodi:role="line">Parameters and</tspan><tspan
+ style="fill:#000000;stroke-width:0.105503"
+ y="88.451942"
+ x="77.626938"
+ sodipodi:role="line"
+ id="tspan3040">Storage options</tspan></text>
+ <text
+ id="text1939"
+ y="78.750557"
+ x="-41.095226"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ xml:space="preserve"><tspan
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ y="78.750557"
+ x="-41.095226"
+ sodipodi:role="line"
+ id="tspan3034">Value Space and</tspan><tspan
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ y="88.451942"
+ x="-41.095226"
+ sodipodi:role="line"
+ id="tspan3038">Behaviour</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ x="-19.191803"
+ y="111.20879"
+ id="text1968"><tspan
+ sodipodi:role="line"
+ id="tspan1965"
+ x="-19.191803"
+ y="111.20879"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583">type</tspan></text>
+ <text
+ id="text1972"
+ y="113.24359"
+ x="120.08958"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.976587;stroke-width:0.265;stroke-miterlimit:4;stroke-dasharray:none"
+ y="113.24359"
+ x="120.08958"
+ id="tspan1970"
+ sodipodi:role="line">instance</tspan></text>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1974"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m -60.569299,125.94806 h 72.698771 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -72.698771 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <text
+ id="text1980"
+ y="139.86145"
+ x="-34.512547"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ y="139.86145"
+ x="-34.512547"
+ id="tspan1978"
+ sodipodi:role="line">ABC</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#830000;fill-opacity:1;stroke-width:0.264583"
+ x="180.30632"
+ y="140.46382"
+ id="text1984"><tspan
+ sodipodi:role="line"
+ id="tspan1982"
+ x="180.30632"
+ y="140.46382"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#830000;fill-opacity:1;stroke-width:0.264583">instance</tspan></text>
+ <path
+ d="M 17.347598,126.00309 H 170.2081 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 17.347598 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path1986"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <text
+ xml:space="preserve"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ x="79.869514"
+ y="138.48405"
+ id="text1990"><tspan
+ sodipodi:role="line"
+ id="tspan1988"
+ x="79.869514"
+ y="138.48405"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583">type</tspan></text>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path1992"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="M -60.569299,153.16829 H 49.987465 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H -60.569299 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.70853 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <text
+ id="text1998"
+ y="165.81964"
+ x="-22.653231"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ y="165.81964"
+ x="-22.653231"
+ id="tspan1996"
+ sodipodi:role="line">DType</tspan></text>
+ <path
+ d="m -60.569299,180.38852 h 72.698771 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -72.698771 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 V 182.4536 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z"
+ style="opacity:0.25;fill:#000080;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2004"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <path
+ d="m 175.57697,180.55362 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2006"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <text
+ xml:space="preserve"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ x="-59.010956"
+ y="193.40663"
+ id="text2010"><tspan
+ sodipodi:role="line"
+ id="tspan2008"
+ x="-59.010956"
+ y="193.40663"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583">base dtype</tspan></text>
+ <text
+ id="text2014"
+ y="194.58372"
+ x="184.03754"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ y="194.58372"
+ x="184.03754"
+ id="tspan2012"
+ sodipodi:role="line">element</tspan></text>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path2016"
+ style="opacity:0.25;fill:#000081;fill-opacity:0.4;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="M 17.463123,180.38852 H 170.32495 c 1.14406,0 2.06509,0.92103 2.06509,2.06508 v 15.70853 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 17.463123 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 V 182.4536 c 0,-1.14405 0.92103,-2.06508 2.06509,-2.06508 z" />
+ <text
+ id="text2020"
+ y="193.40663"
+ x="76.606812"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#000081;fill-opacity:1;stroke-width:0.264583"
+ y="193.40663"
+ x="76.606812"
+ id="tspan2018"
+ sodipodi:role="line">dtype</tspan></text>
+ <path
+ sodipodi:nodetypes="sssssssss"
+ inkscape:connector-curvature="0"
+ id="path2022"
+ style="opacity:1;fill:#ddb9b9;fill-opacity:0.796078;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ d="m 175.57697,153.33338 h 65.38081 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 h -65.38081 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z" />
+ <text
+ xml:space="preserve"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#800000;fill-opacity:0.8;stroke-width:0.264583"
+ x="184.03754"
+ y="167.36348"
+ id="text2026"><tspan
+ sodipodi:role="line"
+ id="tspan2024"
+ x="184.03754"
+ y="167.36348"
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#800000;fill-opacity:0.8;stroke-width:0.264583">element</tspan></text>
+ <path
+ d="M 55.175507,153.27835 H 170.22016 c 1.14406,0 2.06509,0.92103 2.06509,2.06509 v 15.54342 c 0,1.14406 -0.92103,2.06509 -2.06509,2.06509 H 55.175507 c -1.14406,0 -2.06509,-0.92103 -2.06509,-2.06509 v -15.54342 c 0,-1.14406 0.92103,-2.06509 2.06509,-2.06509 z"
+ style="opacity:0.25;fill:#d99b00;fill-opacity:1;stroke:none;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:0.497957"
+ id="path2031"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssssssss" />
+ <text
+ id="text2035"
+ y="166.21391"
+ x="95.410606"
+ style="font-size:11.263px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Semi-Bold';fill:#b27d00;fill-opacity:1;stroke-width:0.264583"
+ y="166.21391"
+ x="95.410606"
+ id="tspan2033"
+ sodipodi:role="line">dtype</tspan></text>
+ <path
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 52.572927,70.114137 V 205.33633"
+ id="path3042"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ x="-122.18608"
+ y="110.75799"
+ id="text3050"><tspan
+ id="tspan3048"
+ sodipodi:role="line"
+ x="-122.18608"
+ y="110.75799"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503">Python type</tspan></text>
+ <text
+ xml:space="preserve"
+ id="text3052"
+ style="font-size:3.52778px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect3054);" />
+ <text
+ id="text3062"
+ y="133.91008"
+ x="-122.18608"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ xml:space="preserve"><tspan
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ y="133.91008"
+ x="-122.18608"
+ sodipodi:role="line"
+ id="tspan3060">Python type</tspan><tspan
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ y="143.61147"
+ x="-122.18608"
+ sodipodi:role="line"
+ id="tspan3064">with ABC</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ x="-140.57703"
+ y="165.22876"
+ id="text3070"><tspan
+ id="tspan3068"
+ sodipodi:role="line"
+ x="-140.57703"
+ y="165.22876"
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503">NEP 41 Proposal</tspan></text>
+ <text
+ id="text3076"
+ y="193.20123"
+ x="-117.83562"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:7.72103px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke-width:0.105503"
+ xml:space="preserve"><tspan
+ style="font-size:7.76111px;fill:#000000;stroke-width:0.105503"
+ y="193.20123"
+ x="-117.83562"
+ sodipodi:role="line"
+ id="tspan3074">Alternative</tspan></text>
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path960"
+ d="M 244.3569,149.56007 H -141.19857"
+ style="fill:none;stroke:#808080;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/doc/neps/nep-0040-legacy-datatype-impl.rst b/doc/neps/nep-0040-legacy-datatype-impl.rst
index c247e3d62..39889109d 100644
--- a/doc/neps/nep-0040-legacy-datatype-impl.rst
+++ b/doc/neps/nep-0040-legacy-datatype-impl.rst
@@ -13,15 +13,15 @@ NEP 40 — Legacy Datatype Implementation in NumPy
.. note::
- This NEP is part of a series of NEPs encompassing first information
- about the previous dtype implementation and issues with it in NEP 40
- (this document).
- :ref:`NEP 41 <NEP41>` then provides an overview and generic design choices
- for the refactor.
- Further NEPs 42 and 43 go into the technical details of the datatype
- and universal function related internal and external API changes.
- In some cases it may be necessary to consult the other NEPs for a full
- picture of the desired changes and why these changes are necessary.
+ This NEP is first in a series:
+
+ - NEP 40 (this document) explains the shortcomings of NumPy's dtype implementation.
+
+ - :ref:`NEP 41 <NEP41>` gives an overview of our proposed replacement.
+
+ - :ref:`NEP 42 <NEP42>` describes the new design's datatype-related APIs.
+
+ - NEP 43 describes the new design's API for universal functions.
@@ -44,6 +44,8 @@ of the current implementation of dtypes as well as a discussion.
In many cases subsections will be split roughly to first describe the
current implementation and then follow with an "Issues and Discussion" section.
+.. _parametric-datatype-discussion:
+
Parametric Datatypes
^^^^^^^^^^^^^^^^^^^^
@@ -253,6 +255,8 @@ types such as ``np.inexact`` (see figure below).
In fact, some control flow within NumPy currently uses
``issubclass(a.dtype.type, np.inexact)``.
+.. _nep-0040_dtype-hierarchy:
+
.. figure:: _static/nep-0040_dtype-hierarchy.png
**Figure:** Hierarchy of NumPy scalar types reproduced from the reference
@@ -335,7 +339,7 @@ Each of these signatures is associated with a single inner-loop function defined
in C, which does the actual calculation, and may be called multiple times.
The main step in finding the correct inner-loop function is to call a
-:c:type:`PyUFunc_TypeResolutionFunc` which retrieves the input dtypes from
+:c:type:`PyUFunc_TypeResolutionFunc` which retrieves the input dtypes from
the provided input arrays
and will determine the full type signature (including output dtype) to be executed.
@@ -366,7 +370,7 @@ It is currently only possible for user defined functions to be found/resolved
if any of the inputs (or the outputs) has the user datatype, since it uses the
`OO->O` signature.
For example, given that a ufunc loop to implement ``fraction_divide(int, int)
--> Fraction`` has been implemented,
+-> Fraction`` has been implemented,
the call ``fraction_divide(4, 5)`` (with no specific output dtype) will fail
because the loop that
includes the user datatype ``Fraction`` (as output) can only be found if any of
@@ -572,7 +576,7 @@ Related Work
------------
* Julia types are an interesting blueprint for a type hierarchy, and define
- abstract and concrete types [julia-types]_.
+ abstract and concrete types [julia-types]_.
* In Julia promotion can occur based on abstract types. If a promoter is
defined, it will cast the inputs and then Julia can then retry to find
@@ -607,7 +611,7 @@ the following provides a subset for more recent ones:
* https://hackmd.io/ok21UoAQQmOtSVk6keaJhw and https://hackmd.io/s/ryTFaOPHE
(2019-04-30) Proposals for subclassing implementation approach.
-
+
* Discussion about the calling convention of ufuncs and need for more
powerful UFuncs: https://github.com/numpy/numpy/issues/12518
diff --git a/doc/neps/nep-0041-improved-dtype-support.rst b/doc/neps/nep-0041-improved-dtype-support.rst
index 6dc4ea50c..d7a08562d 100644
--- a/doc/neps/nep-0041-improved-dtype-support.rst
+++ b/doc/neps/nep-0041-improved-dtype-support.rst
@@ -15,15 +15,15 @@ NEP 41 — First step towards a new Datatype System
.. note::
- This NEP is part of a series of NEPs encompassing first information
- about the previous dtype implementation and issues with it in
- :ref:`NEP 40 <NEP40>`.
- NEP 41 (this document) then provides an overview and generic design
- choices for the refactor.
- Further NEPs 42 and 43 go into the technical details of the datatype
- and universal function related internal and external API changes.
- In some cases it may be necessary to consult the other NEPs for a full
- picture of the desired changes and why these changes are necessary.
+ This NEP is second in a series:
+
+ - :ref:`NEP 40 <NEP40>` explains the shortcomings of NumPy's dtype implementation.
+
+ - NEP 41 (this document) gives an overview of our proposed replacement.
+
+ - :ref:`NEP 42 <NEP42>` describes the new design's datatype-related APIs.
+
+ - NEP 43 describes the new design's API for universal functions.
Abstract
@@ -412,27 +412,28 @@ multiple development stages are required:
* Phase II: Incrementally define or rework API
- * Create a new and easily extensible API for defining new datatypes
- and related functionality. (NEP 42)
-
- * Incrementally define all necessary functionality through the new API (NEP 42):
-
- * Defining operations such as ``np.common_type``.
- * Allowing to define casting between datatypes.
- * Add functionality necessary to create a numpy array from Python scalars
- (i.e. ``np.array(...)``).
- * …
-
- * Restructure how universal functions work (NEP 43), in order to:
-
- * make it possible to allow a `~numpy.ufunc` such as ``np.add`` to be
- extended by user-defined datatypes such as Units.
-
- * allow efficient lookup for the correct implementation for user-defined
- datatypes.
-
- * enable reuse of existing code. Units should be able to use the
- normal math loops and add additional logic to determine output type.
+ * Incrementally define all necessary functionality through methods and
+ properties on the DType (NEP 42):
+
+ * The properties of the class hierarchy and DType class itself,
+ including methods not covered by the following, most central, points.
+ * The functionality that will support dtype casting using ``arr.astype()``
+ and casting related operations such as ``np.common_type``.
+ * The implementation of item access and storage, and the way shape and
+ dtype are determined when creating an array with ``np.array()``
+ * Create a public C-API to define new DTypes.
+
+ * Restructure how universal functions work (NEP 43), to allow extending
+ a `~numpy.ufunc` such as ``np.add`` for user-defined datatypes
+ such as Units:
+
+ * Refactor how the low-level C functions are organized to make it
+ extensible and flexible enough for complicated DTypes such as Units.
+ * Implement registration and efficient lookup for these low-level C
+ functions as defined by the user.
+ * Define how promotion will be used to implement behaviour when casting
+ is required. For example ``np.float64(3) + np.int32(3)`` promotes the
+ ``int32`` to a ``float64``.
* Phase III: Growth of NumPy and Scientific Python Ecosystem capabilities:
@@ -583,7 +584,7 @@ special methods move from the dtype instances to methods on the new DType class.
This is the typical design pattern used in Python.
Organizing these methods and information in a more Pythonic way provides a
solid foundation for refining and extending the API in the future.
-The current API cannot be extended due to how it is exposed publically.
+The current API cannot be extended due to how it is exposed publicly.
This means for example that the methods currently stored in ``PyArray_ArrFuncs``
on each datatype (see :ref:`NEP 40 <NEP40>`)
will be defined differently in the future and
@@ -620,6 +621,49 @@ While DType and Scalar describe the same concept/type (e.g. an `int64`),
it seems practical to split out the information and functionality necessary
for numpy into the DType class.
+The dtype instances provide parameters and storage options
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+From a computer science point of view a type defines the *value space*
+(all possible values its instances can take) and their *behaviour*.
+As proposed in this NEP, the DType class defines value space and behaviour.
+The ``dtype`` instance can be seen as part of the value, so that the typical
+Python ``instance`` corresponds to ``dtype + element`` (where *element* is the
+data stored in the array).
+An alternative view would be to define value space and behaviour on the
+``dtype`` instances directly.
+These two options are presented in the following figure and compared to
+similar Python implementation patterns:
+
+.. image:: _static/nep-0041-type-sketch-no-fonts.svg
+
+The difference is in how parameters, such as string length or the datetime
+units (``ms``, ``ns``, ...), and storage options, such as byte-order, are handled.
+When implementing a Python (scalar) ``type`` parameters, for example the datetimes
+unit, will be stored in the instance.
+This is the design NEP 42 tries to mimic, however, the parameters are now part
+of the dtype instance, meaning that part of the data stored in the instance
+is shared by all array elements.
+As mentioned previously, this means that the Python ``instance`` corresponds
+to the ``dtype + element`` stored in a NumPy array.
+
+An more advanced approach in Python is to use a class factory and an abstract
+base class (ABC).
+This allows moving the parameter into the dynamically created ``type`` and
+behaviour implementation may be specific to those parameters.
+An alternative approach might use this model and implemented behaviour
+directly on the ``dtype`` instance.
+
+We believe that the version as proposed here is easier to work with and understand.
+Python class factories are not commonly used and NumPy does not use code
+specialized for dtype parameters or byte-orders.
+Making such specialization easier to implement such specialization does not
+seem to be a priority.
+One result of this choice is that some DTypes may only have a singleton instance
+if they have no parameters or storage variation.
+However, all of the NumPy dtypes require dynamically created instances due
+to allowing metadata to be attached.
+
Scalars should not be instances of the datatypes (2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/neps/nep-0042-new-dtypes.rst b/doc/neps/nep-0042-new-dtypes.rst
index b37555892..2d1e3a329 100644
--- a/doc/neps/nep-0042-new-dtypes.rst
+++ b/doc/neps/nep-0042-new-dtypes.rst
@@ -1,9 +1,12 @@
-========================================
-NEP 42 — Implementation of New DataTypes
-========================================
+.. _NEP42:
-:title: Extensible Datatypes for NumPy
+==============================================================================
+NEP 42 — User-extensible dtypes
+==============================================================================
+
+:title: User-extensible dtypes
:Author: Sebastian Berg
+:Author: Ben Nathanson
:Author: Marten van Kerkwijk
:Status: Draft
:Type: Standard
@@ -12,666 +15,439 @@ NEP 42 — Implementation of New DataTypes
.. note::
- This NEP is part of a series of NEPs encompassing first information
- about the previous dtype implementation and issues with it in
- :ref:`NEP 40 <NEP40>`.
- :ref:`NEP 41 <NEP41>` then provides an overview and generic design
- choices for the refactor. NEPs 42 (this document)
- and 43 go into the technical details of the internal and external
- API changes related to datatypes and universal functions, respectively.
- In some cases it may be necessary to consult the other NEPs for a full
- picture of the desired changes and why these changes are necessary.
+ This NEP is third in a series:
+ - :ref:`NEP 40 <NEP40>` explains the shortcomings of NumPy's dtype implementation.
-Abstract
---------
-
-NEP 40 and 41 detailed the need for the creation of a new datatype system within
-NumPy to better serve downstream use-cases and improve the maintainability
-and the extensibility of NumPy.
-A main issue with the current dtype API is that datatypes are written as
-a single Python class with special instances for each of the actual datatypes.
-While this certainly has been a practical approach in implementing numerical
-datatypes, it does not allow to naturally split up logic. For example,
-functions such as ``can_cast`` have explicit logic for each datatype.
-Because of this monolithic code structure user-defined datatypes do not have
-the same capabilities as NumPy datatypes have.
-The current structure also makes understanding and modifying datatypes harder.
-The current datatypes are not well encapsulated, so modifications targeting
-a single datatype inevitably touch code involving others.
-As detailed in NEP 41, the desired general design is to create classes for
-each of the NumPy-provided datatypes, meaning that ``np.dtype("float64")``
-returns an instance of a ``Float64`` class which is a subclass of ``np.dtype``.
-``np.dtype[float64]`` will also be used to denote this class.
-This will allow moving all logic into special methods on the ``np.dtype``
-subclasses. This ``DType`` class would then serve as the central
-extension point for adding new dtypes to NumPy.
-
-This document proposes the new API for the datatypes itself.
-A second proposal NEP 43 details proposed changes to the universal
-functions.
-Note that only the implementation of both NEPs will provide the desired full
-functionality.
+ - :ref:`NEP 41 <NEP41>` gives an overview of our proposed replacement.
+ - NEP 42 (this document) describes the new design's datatype-related APIs.
-.. note::
+ - NEP 43 describes the new design's API for universal functions.
- At this time this NEP is in a preliminary state. Both internal and
- external API may be adapted based on user input or implementation needs.
- The general design principles and choices, while provisional, should not
- be expected to change dramatically.
+******************************************************************************
+Abstract
+******************************************************************************
-Detailed Description
---------------------
+NumPy's dtype architecture is monolithic, built around a single class that
+handles each dtype as an instance. There's no principled way to expand it to
+new dtypes, and the code is difficult to read and maintain.
-NEP 41 layed out the creation of a class hierarchy for datatypes using the
-new DType classes to provide all necessary implementations.
-This NEP defines the specific choice of API necessary to define new DTypes.
-Here, these are suggested as C-API slots; however, conceptually these
-translate identically to Python methods.
+As NEP 41 explains, we are proposing a new architecture that is modular and
+open to user additions. dtypes will derive from a new ``DType`` class serving
+as the extension point for new types. ``np.dtype("float64")`` will return an
+instance of a ``Float64`` class, a subclass of root class ``np.dtype``.
-Additionally, the NEP proposes to implement the notion of *abstract* DTypes.
-Further, we detail – in part – how the proposed methods (C-API slots)
-enable all necessary use cases.
+This NEP is one of two that lay out the design and API of this new
+architecture. This NEP addresses dtype implementation; NEP 43 addresses
+universal functions.
-Each section will begin with a short motivation of the issue or what
-problem is addressed. This is followed by a description of the proposed
-design choice, and then may list alternatives.
+.. note::
+ Details of the private and external APIs may change to reflect user
+ comments and implementation constraints. The underlying principles and
+ choices should not change significantly.
-Nomenclature
-""""""""""""
-As a brief note on nomenclature, it should be noted that ``dtype`` normally
-denotes the dtype *instance*, which is the object attached to a numpy array.
-On the other hand the ``DType`` class is the subclass of ``np.dtype``.
-On the C-level we currently use the name ``descriptor`` or ``descr``
-interchangeably with *dtype instance*. ``descriptor`` or ``descr`` will be
-used in proposed C-API names to differentiate dtype instances from DType
-classes more clearly.
-Note that the notion of dtype class is currently represented mainly as
-the ``dtype.num`` and ``dtype.char``.
-Please see the :ref:`dtype hierarchy figure <hierarchy_figure>` for an
-illustration of this distinction.
+******************************************************************************
+Motivation and scope
+******************************************************************************
-There are currently classes in NumPy for numeric types e.g.
-``np.float64``; however,
-these are not DTypes but the corresponding scalar classes
-(see also NEP 40 and 41 for discussion on why these are largely unrelated to
-the proposed changes).
+Our goal is to allow user code to create fully featured dtypes for a broad
+variety of uses, from physical units (such as meters) to domain-specific
+representations of geometric objects. NEP 41 describes a number of these new
+dtypes and their benefits.
+Any design supporting dtypes must consider:
-Proposed access to DType class
-""""""""""""""""""""""""""""""
+- How shape and dtype are determined when an array is created
+- How array elements are stored and accessed
+- The rules for casting dtypes to other dtypes
-**Motivation:**
+In addition:
-Currently we often call ``np.dtype`` to create the dtype instance
-corresponding to a given scalar type (e.g. ``np.dtype(np.int64)``).
-Adding the DType classes may require a way to access the classes conveniently.
+- We want dtypes to comprise a class hierarchy open to new types and to
+ subhierarchies, as motivated in :ref:`NEP 41 <NEP41>`.
-**Description:**
+And to provide this,
-To avoid duplication, but also to expose the classes conveniently to users
-we propose the addition of::
+- We need to define a user API.
- np.dtype[np.int64]
+All these are the subjects of this NEP.
-as a class getter. This can work both for user and NumPy DTypes,
-although, in many cases a library may choose to provide a more direct
-way to access the specific DType class.
-This method may initially be limited to concrete DTypes.
-The main reason for this choice is to provide a single
-clear and future-proof way to find the DType class given the
-Python (scalar) class.
+- The class hierarchy, its relation to the Python scalar types, and its
+ important attributes are described in `DType class`_.
-This should not be a common operation, so providing this class getter reduces
-the pressure of adding the new DType classes into the namespace.
+- The functionality that will support dtype casting is described in `Casting`_.
-*Note: This is currently a possible extension and not yet decided.*
+- The implementation of item access and storage, and the way shape and dtype
+ are determined when creating an array, are described in `Array coercion`_.
+- The functionality for users to define their own DTypes is described in
+ `Public C-API`_.
-Hierarchy of DTypes and Abstract DTypes
-"""""""""""""""""""""""""""""""""""""""
+The API here and in NEP 43 is entirely on the C side. A Python-side version
+will be proposed in a future NEP.
+A future Python API is expected to be similar, but provide a more convenient
+API to reuse the functionality of existing DTypes.
+It could also provide shorthands to create structured DTypes similar to python's
+`dataclasses <https://docs.python.org/3.8/library/dataclasses.html>`_.
-**Motivation:**
-The creation of DType classes has already been decided in NEP 41.
-Here we discuss the notion of **abstract** DTypes.
-There are multiple reasons for this:
-1. It allows the definition of a class hierarchy, in principle allowing checks like
- ``isinstance(np.dtype("float64"), np.inexact)``.
- **This hierarchy may be a prerequisite to implementing dispatching
- for universal functions (NEP 43)**
-2. Abstract DTypes can enable code such as
- ``arr.astype(Complex)`` to express the desire to cast to a
- complex data type of unspecified precision.
-3. It anticipates the creation of families of DTypes by users.
- For example allowing the creation of an abstract ``Unit`` class with a concrete
- ``Float64Unit``. In which case ``Unit(np.float64, "m")`` could be
- identical to ``Float64Unit("m")``.
-
-A very concrete example is the current Pandas ``Categorical`` DType,
-which may benefit from abstraction to allow the differentiation of
-a categorical of integer values and one of general object values.
-The reason for this is that we may want to reject
-``common_dtype(CategoricalInt64, String)``, but accept
-``common_dtype(CategoricalObject, String)`` to be the ``object`` DType.
-The current Pandas ``Categorical`` DType combines both and must remain
-representable. The solution is thus to make ``Categorical`` abstract with
-the two subclasses ``CategoricalInt64`` and ``CategoricalObject``
-distinguishing the two.
-
-
-**Description:**
-
-The figure below shows the proposed datatype hierarchy.
-It should be noted that abstract DTypes are distinct in two ways:
-
-1. They do not have instances. Instantiating an abstract DType has to return
- a concrete subclass or raise an error (default, and possibly enforced
- initially).
-2. Unlike concrete DTypes, abstract DTypes can be superclasses, they may also
- serve like Python's abstract base classes (ABC).
- (It may be possible to simply use/inherit from Python ABCs.)
-
-These two rules are identical to the type choices made for example in the
-`Julia language <https://docs.julialang.org/en/v1/manual/types/#man-abstract-types-1>`_.
-It allows for the creation of a datatype hierarchy, but avoids issues with
-subclassing concrete DTypes directly.
-For example, logic such as ``can_cast`` does not cleanly inherit from a
-``Int64`` to a ``Datetime64`` even though the ``Datetime64`` could be seen
-as an integer with only a unit attached (and thus implemented as a subclass).
-
-The main consequence for the DType implementer is that concrete DTypes can
-never be subclasses of existing concrete DTypes.
-End-users would not notice or need to know about this distinction.
-However, subclassing may be a possible mechanism to extend the datatypes
-in the future to allow specialized implementations for existing dtypes
-such as a GPU float64 subclassing a NumPy float64.
-
-The combination of (initially) rejecting subclassing of concrete DTypes
-while allowing it for abstract ones allows the transparent definition of
-a class hierarchy, while avoiding potential issues with subclassing and
-especially inheritance.
-
-As a technical implementation detail: the DType class will require C-side
-storage of methods and additional information.
-This requires the creation of a ``DTypeMeta`` class.
-Each ``DType`` class is thus an instance of ``DTypeMeta`` with a well-defined
-and extensible interface.
-The end-user will not need to be aware of this.
-
-.. _hierarchy_figure:
-.. figure:: _static/dtype_hierarchy.svg
- :figclass: align-center
-
-
-Methods/Slots defined for each DType
-""""""""""""""""""""""""""""""""""""
-
-NEP 41 detailed that all logic should be defined through special methods
-on the DTypes.
-This section will list a specific set of such methods (in the form of
-Python methods).
-The C-side equivalent slot signature will be summarized below after proposing
-the general C-API for defining new Datatypes.
-Note that while the slots are defined as special Python methods here, this is
-for the readers convenience and *not* meant to imply the identical exposure
-as a Python API.
-This will need to be proposed in a separate, later, NEP.
+******************************************************************************
+Backward compatibility
+******************************************************************************
-Some of the methods may be similar or even reuse existing Python slots.
-User-defined DType classes are discouraged from defining or using Python's
-special slots without consulting the NumPy developers, in order to allow
-defining them later.
-For example ``dtype1 & dtype2`` could be a shorthand for
-``np.common_dtype(dtype1, dtype2)``, and comparisons should be defined mainly
-through casting logic.
+The disruption is expected to be no greater than that of a typical NumPy
+release.
+- The main issues are noted in :ref:`NEP 41 <NEP41>` and will mostly affect
+ heavy users of the NumPy C-API.
-Additional Information
-^^^^^^^^^^^^^^^^^^^^^^
+- Eventually we will want to deprecate the API currently used for creating
+ user-defined dtypes.
-In addition to the more detailed methods below, the following general
-information is currently provided and will be defined on the class:
+- Small, rarely noticed inconsistencies are likely to change. Examples:
-* ``cls.parametric`` (see also `NEP 40 <NEP40>`_):
+ - ``np.array(np.nan, dtype=np.int64)`` behaves differently from
+ ``np.array([np.nan], dtype=np.int64)`` with the latter raising an error.
+ This may require identical results (either both error or both succeed).
+ - ``np.array([array_like])`` sometimes behaves differently from
+ ``np.array([np.array(array_like)])``
+ - array operations may or may not preserve dtype metadata
- * Parametric will be a flag in the (private) C-API. However, the
- Python API will instead use a ``ParametricDType`` class from
- which to inherit. (This is similar to Python's type flags, which include
- flags for some basic subclasses such as subclasses of ``float`` or ``tuple``)
- * This flag is mainly to simplify DType creation and casting and
- allow for performance tweaks.
- * DTypes which are not parametric must define a canonical dtype instance
- which should be a singleton.
- * Parametric dtypes require some additional methods (below).
+The new code must pass NumPy's regular test suite, giving some assurance that
+the changes are compatible with existing code.
-* ``self.canonical`` method (Alternative: new instance attribute)
+******************************************************************************
+Usage and impact
+******************************************************************************
- * Instead of byteorder, we may want a ``canonical`` flag (reusing the
- ISNBO flag – "is native byte order" seems possible here).
- This flag signals that the data are stored in the default/canonical way.
- In practice this is always an NBO check, but generalization should be possible.
- A potential use-case is a complex-conjugated instance of Complex which
- stores ``real - imag`` instead of ``real + imag`` and is thus not
- the canonical storage.
+We believe the few structures in this section are sufficient to consolidate
+NumPy's present functionality and also to support complex user-defined DTypes.
-* ``ensure_canonical(self) -> dtype`` return a new dtype (or ``self``).
- The returned dtype must have the ``canonical`` flag set.
+The rest of the NEP fills in details and provides support for the claim.
-* ``DType.type`` is the associated scalar type. ``dtype.type`` will be a
- class attribute and the current ``dtype.type`` field will be considered
- deprecated. This may be relaxed if a use-case arises.
+Again, though Python is used for illustration, the implementation is a C API only; a
+future NEP will tackle the Python API.
-Additionally, existing methods (and C-side fields) will be provided.
-However, the fields ``kind`` and ``char`` will be set to ``\0``
-(NULL character) on the C-side.
-While discouraged, except for NumPy builtin types, ``kind`` both will return
-the ``__qualname__`` of the object to ensure uniqueness for all DTypes.
-(the replacement for ``kind`` will be to use ``isinstance`` checks).
+After implementing this NEP, creating a DType will be possible by implementing
+the following outlined DType base class,
+that is further described in `DType class`_:
-Another example of methods that should be moved to the DType class are the
-various sorting functions, which shall be implemented by defining a method:
+.. code-block:: python
+ :dedent: 0
-* ``dtype_get_sort_function(self, sortkind="stable") -> sortfunction``
+ class DType(np.dtype):
+ type : type # Python scalar type
+ parametric : bool # (may be indicated by superclass)
-which must return ``NotImplemented`` if the given ``sortkind`` is not known.
-Similarly, any function implemented previously which cannot be removed will
-be implemented as a special method.
-Since these methods can be deprecated and new (renamed) replacements added,
-the API is not defined here and it is acceptable if it changes over time.
+ @property
+ def canonical(self) -> bool:
+ raise NotImplementedError
-For some of the current "methods" defined on the dtype, including sorting,
-a long term solution may be to instead create generalized ufuncs to provide
-the functionality.
+ def ensure_canonical(self : DType) -> DType:
+ raise NotImplementedError
-**Alternatives:**
+For casting, a large part of the functionality is provided by the "methods" stored
+in ``_castingimpl``
-Some of these flags could be implemented by inheriting
-for example from a ``ParametricDType`` class. However, on the C-side as
-an implementation detail it seems simpler to provide a flag.
-This does not preclude the possibility of creating a ``ParametricDType``
-to Python to represent the same thing.
+.. code-block:: python
+ :dedent: 0
-**Example:**
+ @classmethod
+ def common_dtype(cls : DTypeMeta, other : DTypeMeta) -> DTypeMeta:
+ raise NotImplementedError
-The ``datetime64`` DType is considered parametric, due to its unit, and
-unlike a float64 has no canonical representation. The associated ``type``
-is the ``np.datetime64`` scalar.
+ def common_instance(self : DType, other : DType) -> DType:
+ raise NotImplementedError
+ # A mapping of "methods" each detailing how to cast to another DType
+ # (further specified at the end of the section)
+ _castingimpl = {}
-**Issues and Details:**
+For array-coercion, also part of casting:
-A potential DType such as ``Categorical`` will not be required to have a clear type
-associated with it. Instead, the ``type`` may be ``object`` and the
-categorical's values are arbitrary objects.
-Unlike with well-defined scalars, this ``type`` cannot
-not be used for the dtype discovery necessary for coercion
-(compare section `DType Discovery during Array Coercion`_).
-
-
-Coercion to and from Python Objects
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. code-block:: python
+ :dedent: 0
-**Motivation:**
+ def __dtype_setitem__(self, item_pointer, value):
+ raise NotImplementedError
-When storing a single value in an array or taking it out of the array,
-it is necessary to coerce (convert) it to and from the low-level
-representation inside the array.
+ def __dtype_getitem__(self, item_pointer, base_obj) -> object:
+ raise NotImplementedError
-**Description:**
+ @classmethod
+ def __discover_descr_from_pyobject__(cls, obj : object) -> DType:
+ raise NotImplementedError
-Coercing to and from Python scalars requires two to three methods:
+ # initially private:
+ @classmethod
+ def _known_scalar_type(cls, obj : object) -> bool:
+ raise NotImplementedError
-1. ``__dtype_setitem__(self, item_pointer, value)``
-2. ``__dtype_getitem__(self, item_pointer, base_obj) -> object``
- The ``base_obj`` should be ignored normally, it is provided *only* for
- memory management purposes, pointing to an object owning the data.
- It exists only to allow support of structured datatypes with subarrays
- within NumPy, which (currently) return views into the array.
- The function returns an equivalent Python scalar (i.e. typically a NumPy
- scalar).
-3. ``__dtype_get_pyitem__(self, item_pointer, base_obj) -> object``
- (initially hidden for new-style user-defined datatypes, may be exposed
- on user request). This corresponds to the ``arr.item()`` method which
- is also used by ``arr.tolist()`` and returns e.g. Python floats instead of
- NumPy floats.
-(The above is meant for C-API. A Python-side API would have to use byte
-buffers or similar to implement this, which may be useful for prototyping.)
+Other elements of the casting implementation is the ``CastingImpl``:
-These largely correspond to the current definitions. When a certain scalar
-has a known (different) dtype, NumPy may in the future use casting instead
-of ``__dtype_setitem__``.
-A user datatype is (initially) expected to implement ``__dtype_setitem__``
-for its own ``DType.type`` and all basic Python scalars it wishes to support
-(e.g. integers, floats, datetime).
-In the future a function "``known_scalartype``" may be added to allow a user
-dtype to signal which Python scalars it can store directly.
+.. code-block:: python
+ :dedent: 0
+ casting = Union["safe", "same_kind", "unsafe"]
-**Implementation:**
+ class CastingImpl:
+ # Object describing and performing the cast
+ casting : casting
-The pseudo-code implementation for setting a single item in an array
-from an arbitrary Python object ``value`` is (note that some of the
-functions are only defined below)::
-
- def PyArray_Pack(dtype, item_pointer, value):
- DType = type(dtype)
- if DType.type is type(value) or DType.known_scalartype(type(value)):
- return dtype.__dtype_setitem__(item_pointer, value)
-
- # The dtype cannot handle the value, so try casting:
- arr = np.array(value)
- if arr.dtype is object or arr.ndim != 0:
- # not a numpy or user scalar; try using the dtype after all:
- return dtype.__dtype_setitem__(item_pointer, value)
-
- arr.astype(dtype)
- item_pointer.write(arr[()])
-
-where the call to ``np.array()`` represents the dtype discovery and is
-not actually performed.
+ def resolve_descriptors(self, Tuple[DType] : input) -> (casting, Tuple[DType]):
+ raise NotImplementedError
-**Example:**
+ # initially private:
+ def _get_loop(...) -> lowlevel_C_loop:
+ raise NotImplementedError
-Current ``datetime64`` returns ``np.datetime64`` scalars and can be assigned
-from ``np.datetime64``.
-However, the datetime ``__dtype_setitem__`` also allows assignment from
-date strings ("2016-05-01") or Python integers.
-Additionally the datetime ``__dtype_get_pyitem__`` function actually returns
-Python ``datetime.datetime`` object (most of the time).
+which describes the casting from one DType to another.
+In NEP 43 this ``CastingImpl`` object is used unchanged to support
+universal functions.
-**Alternatives:**
+******************************************************************************
+Definitions
+******************************************************************************
+.. glossary::
-This may be seen as simply a cast to and from the ``object`` dtype.
-However, it seems slightly more complicated. This is because
-in general a Python object could itself be a zero-dimensional array or
-scalar with an associated DType.
-Thus, representing it as a normal cast would either require that:
+ dtype
+ The dtype *instance*; this is the object attached to a numpy array.
-* The implementor handles all Python classes, even those for which
- ``np.array(scalar).astype(UserDType)`` already works because
- ``np.array(scalar)`` returns, say, a datetime64 array.
-* The cast is actually added between a typed-object to dtype. And even
- in this case a generic fallback (for example ``float64`` can use
- ``float(scalar)`` to do the cast) is also necessary.
+ DType
+ Any subclass of the base type ``np.dtype``.
-It is certainly possible to describe the coercion to and from Python objects
-using the general casting machinery. However, it seems special enough to
-handle specifically.
+ coercion
+ Conversion of Python types to NumPy arrays and values stored in a NumPy
+ array.
+ cast
+ Conversion of an array to a different dtype.
-**Further Issues and Discussion:**
+ promotion
+ Finding a dtype that can perform an operation on a mix of dtypes without
+ loss of information.
-The setitem function currently duplicates some code, such as coercion
-from a string. ``datetime64`` allows assignment from string, but the same
-conversion also occurs for casts from the string dtype to ``datetime64``.
-In the future, we may expose a way to signal whether a conversion is known,
-and otherwise a normal cast is made so that the item is effectively set to ``np.array(scalar).astype(requested_dtype)``.
+ safe cast
+ A cast is safe if no information is lost when changing type.
-There is a general issue about the handling of subclasses. We anticipate to not
-automatically detect the dtype for ``np.array(float64_subclass)`` to be
-float64. The user can still provide ``dtype=np.float64``. However, the above
-"assign by casting" using ``np.array(scalar_subclass).astype(requested_dtype)``
-will fail.
+On the C level we use ``descriptor`` or ``descr`` to mean
+*dtype instance*. In the proposed C-API, these terms will distinguish
+dtype instances from DType classes.
.. note::
+ Perhaps confusingly, NumPy already has a class hierarchy for numeric types, as
+ seen :ref:`in the figure <nep-0040_dtype-hierarchy>` of NEP 40, and the new
+ DType hierarchy will resemble it. But the existing hierarchy is for scalar
+ types, not DTypes, and its existence is largely irrelevant here, as NEP 40 and
+ 41 explain.
- This means that ``np.complex256`` should not use ``__float__`` in its
- ``__dtype_setitem__`` method in the future unless it is a known floating
- point type. If the scalar is a subclass of a different high precision
- floating point type (e.g. ``np.float128``) then this will lose precision.
-
-
-DType Discovery during Array Coercion
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-An important step in the usage of NumPy arrays is the creation of the array
-itself from collections of generic Python objects.
-
-**Motivation:**
-
-Although the distinction is not clear currently, there are two main needs::
-
- np.array([1, 2, 3, 4.])
-
-needs to guess the correct dtype based on the Python objects inside.
-Such an array may include a mix of datatypes, as long as they can be clearly
-promoted.
-Currently not clearly distinct (but partially existing for strings) is the
-use case of::
-
- # np.dtype[np.str_] can also be spelled np.str_ or "S" (which works today)
- np.array([object(), None], dtype=np.dtype[np.str_])
-
-which forces each object to be interpreted as string. This is anticipated
-to be useful for example for categorical datatypes::
-
- np.array([1, 2, 1, 1, 2], dtype=Categorical)
+.. _DType class:
-to allow the discovery the of all unique values.
-(For NumPy ``datetime64`` this is also currently used to allow string input.)
-
-There are three further issues to consider:
-
-1. It may be desirable that datatypes can be created which are associated
- to normal Python scalars (such as ``datetime.datetime``), which do not
- have a ``dtype`` attribute already.
-2. In general, a datatype could represent a sequence, however, NumPy currently
- assumes that sequences are always collections of elements (the sequence cannot be an
- element itself). An example for this is would be a ``vector`` DType.
-3. An array may itself contain arrays with a specific dtype (even
- general Python objects). For example:
- ``np.array([np.array(None, dtype=object)], dtype=np.String)``
- poses the issue of how to handle the included array.
-
-Some of these difficulties arise due to the fact that finding the correct shape
-of the output array and finding the correct datatype are closely related.
-
-**Implementation:**
-
-There are two distinct cases given above: First, when the user has provided no
-dtype information, and second when the user provided a DType class –
-a notion that is currently represented e.g. by the parametric instance ``"S"``
-representing a string of any length.
-
-In the first case, it is necessary to establish a mapping from the Python type(s)
-of the constituent elements to the DType class.
-When the DType class is known, the correct dtype instance still needs to be found.
-This shall be implemented by leveraging two pieces of information:
-
-1. ``DType.type``: The current type attribute to indicate which Python scalar
- type is associated with the DType class (this is a *class* attribute that always
- exists for any datatype and is not limited to array coercion).
-2. The reverse lookup will remain hardcoded for the basic Python types initially.
- Otherwise the ``type`` attribute will be used, and at least initially may
- enforce deriving the scalar from a NumPy-provided scalar base class.
- This method may be expanded later (see alternatives).
-3. ``__discover_descr_from_pyobject__(cls, obj) -> dtype``: A classmethod that
- returns the correct descriptor given the input object.
- *Note that only parametric DTypes have to implement this*, most datatypes
- can simply use a default (singleton) dtype instance which is found only
- based on the ``type(obj)`` of the Python object.
+******************************************************************************
+The DType class
+******************************************************************************
-The Python type which is already associated with a DType through the
-``DType.type`` attribute maps from the DType to the Python type.
-A DType may choose to automatically discover from this Python type.
-This will be achieved using a global a mapping (dictionary-like) of::
+This section reviews the structure underlying the proposed DType class,
+including the type hierarchy and the use of abstract DTypes.
- known_python_types[type] = DType
+Class getter
+==============================================================================
-To anticipate the possibility of creating both a Python type (``pytype``)
-and ``DType`` dynamically, and thus the potential desire to delete them again,
-this mapping should generally be weak.
-This requires that the ``pytype`` holds on to the ``DType`` explicitly.
-Thus, in addition to building the global mapping, NumPy will store
-the ``DType`` as ``pytype.__associated_array_dtype__`` in the Python type.
-This does *not* define the mapping and should *not* be accessed directly.
-In particular potential inheritance of the attribute does not mean that
-NumPy will use the superclasses ``DType`` automatically.
-A new ``DType`` must be created for the subclass.
+To create a dtype instance from a scalar type users now call ``np.dtype`` (for
+instance, ``np.dtype(np.int64)``).
-.. note::
+To get the DType of a scalar type, we propose this getter syntax::
- Python integers do not have a clear/concrete NumPy type associated with
- them right now. This is because during array coercion NumPy currently
- finds the first type capable of representing their value in the list
- of `long`, `unsigned long`, `int64`, `unsigned int64`, and `object`
- (on many machines `long` is 64 bit).
-
- Instead they will need to be implemented using an
- ``AbstractPyInt``. This DType class can then provide
- ``__discover_descr_from_pyobject__`` and return the actual dtype which
- is e.g. ``np.dtype("int64")``.
- For dispatching/promotion in ufuncs, it will also be necessary
- to dynamically create ``AbstractPyInt[value]`` classes (creation can be
- cached), so that they can provide the current value based promotion
- functionality provided by ``np.result_type(python_integer, array)`` [1]_.
-
-To allow for a DType to accept specific inputs as known scalars, we will
-initially use a ``known_scalar_type`` method.
-This allows discovery of a ``vector`` as a scalar (element) instead of
-a sequence (for the command ``np.array(vector, dtype=VectorDType)``)
-even when ``vector`` is itself a sequence or even an array subclass.
-This will *not* be public API initially, but may be made public at a later
-time.
-
-This will work similar to the following pseudo-code::
+ np.dtype[np.int64]
- def find_dtype(array_like):
- common_dtype = None
- for element in array_like:
- # default to object dtype, if unknown
- DType = known_python_types.get(type(element), np.dtype[object])
- dtype = DType.__discover_descr_from_pyobject__(element)
+The notation works equally well with built-in and user-defined DTypes
+and is inspired by and potentially useful for type hinting.
- if common_dtype is None:
- common_dtype = dtype
- else:
- common_dtype = np.promote_types(common_dtype, dtype)
+This getter eliminates the need to create an explicit name for every
+DType, crowding the ``np`` namespace; the getter itself signifies the type.
-In practice, we have to find out whether an element is actually a sequence.
-This means that instead of using the ``object`` dtype directly, we have to
-check whether or not it is a sequence.
+Since getter calls won't be needed often, this is unlikely to be burdensome.
+Classes can also offer concise alternatives.
-The full algorithm (without user provided dtype) thus looks more like::
+The initial implementation probably will return only concrete (not abstract)
+DTypes.
- def find_dtype_recursive(array_like, dtype=None):
- """
- Recursively find the dtype for a nested sequences (arrays are not
- supported here).
- """
- DType = known_python_types.get(type(element), None)
+*This item is still under review.*
- if DType is None and is_array_like(array_like):
- # Code for a sequence, an array_like may have a DType we
- # can use directly:
- for element in array_like:
- dtype = find_dtype_recursive(element, dtype=dtype)
- return dtype
- elif DType is None:
- DType = np.dtype[object]
+Hierarchy and abstract classes
+==============================================================================
- # Same as above
+We will use abstract classes as building blocks of our extensible DType class
+hierarchy.
-If the user provides ``DType``, then this DType will be tried first, and the
-``dtype`` may need to be cast before the promotion is performed.
+1. Abstract classes are inherited cleanly, in principle allowing checks like
+ ``isinstance(np.dtype("float64"), np.inexact)``.
-**Limitations:**
-
-The above issue 3. is currently (sometimes) supported by NumPy so that
-the values of an included array are inspected.
-Support in those cases may be kept for compatibility, however,
-it will not be exposed to user datatypes.
-This means that if e.g. an array with a parametric string dtype is coerced above
-(or cast) to an array of a fixed length string dtype (with unknown length),
-this will result in an error.
-Such a conversion will require passing the correct DType (fixed length of the
-string) or providing a utility function to the user.
-
-The use of a global type map means that an error or warning has to be given
-if two DTypes wish to map to the same Python type. In most cases user
-DTypes should only be implemented for types defined within the same library to
-avoid the potential for conflicts.
-It will be the DType implementor's responsibility to be careful about this and use
-the flag to disable registration when in doubt.
-
-**Alternatives:**
-
-The above proposes to add a global mapping, however, initially limiting it
-to types deriving from a NumPy subclass (and a fixed set of Python types).
-This could be relaxed in the future.
-Alternatively, we could rely on the scalar belonging to the user dtype to
-implement ``scalar.__associated_array_dtype__`` or similar.
-
-Initially, the exact implementation shall be *undefined*, if
-scalars will have to derive from a NumPy scalar, they will also have
-a ``.__associated_array_dtype__`` attribute.
-At this time, a future update may to use this instead of a global mapping,
-however, it makes NumPy a hard dependency for the scalar class.
-
-An initial alternative suggestion was to use a two-pass approach instead.
-The first pass would only find the correct DType class, and the second pass
-would then find correct dtype instance (the second pass is often not necessary).
-The advantage of this is that the DType class information is vital for universal
-functions to decide which loop to execute.
-The first pass would provide the full information necessary for value-based
-casting currently implemented for scalars, giving even the possibility of
-expanding it to e.g. list inputs ``np.add(np.array([8], dtype="uint8"), [4])``
-giving a ``uint8`` result.
-This is mainly related to the question to how the common dtype is found above.
-It seems unlikely that this is useful, and similar to a global, could be
-added later if deemed necessary.
-
-**Further Issues and Discussion:**
-
-While it is possible to create e.g. a DType such as Categorical, array,
-or vector which can only be used if `dtype=DType` is provided, if this
-is necessary these will not roundtrip correctly when converted back
-and forth::
+2. Abstract classes allow a single piece of code to handle a multiplicity of
+ input types. Code written to accept Complex objects can work with numbers
+ of any precision; the precision of the results is determined by the
+ precision of the arguments.
+
+3. There is room for user-created families of DTypes. We can envision an
+ abstract ``Unit`` class for physical units, with a concrete subclass like
+ ``Float64Unit``. Calling ``Unit(np.float64, "m")`` (``m`` for meters) would
+ be equivalent to ``Float64Unit("m")``.
+
+4. The implementation of universal functions in NEP 43 may require
+ a class hierarchy.
+
+**Example:** A NumPy ``Categorical`` class would be a match for pandas
+``Categorical`` objects, which can contain integers or general Python objects.
+NumPy needs a DType that it can assign a Categorical to, but it also needs
+DTypes like ``CategoricalInt64`` and ``CategoricalObject`` such that
+``common_dtype(CategoricalInt64, String)`` raises an error, but
+``common_dtype(CategoricalObject, String)`` returns an ``object`` DType. In
+our scheme, ``Categorical`` is an abstract type with ``CategoricalInt64`` and
+``CategoricalObject`` subclasses.
+
+
+Rules for the class structure, illustrated :ref:`below <nep42_hierarchy_figure>`:
+
+1. Abstract DTypes cannot be instantiated. Instantiating an abstract DType
+ raises an error, or perhaps returns an instance of a concrete subclass.
+ Raising an error will be the default behavior and may be required initially.
+
+2. While abstract DTypes may be superclasses, they may also act like Python's
+ abstract base classes (ABC) allowing registration instead of subclassing.
+ It may be possible to simply use or inherit from Python ABCs.
+
+3. Concrete DTypes may not be subclassed. In the future this might be relaxed
+ to allow specialized implementations such as a GPU float64 subclassing a
+ NumPy float64.
+
+The
+`Julia language <https://docs.julialang.org/en/v1/manual/types/#man-abstract-types-1>`_
+has a similar prohibition against subclassing concrete types.
+For example methods such as the later ``__common_instance__`` or
+``__common_dtype__`` cannot work for a subclass unless they were designed
+very carefully.
+It helps avoid unintended vulnerabilities to implementation changes that
+result from subclassing types that were not written to be subclassed.
+We believe that the DType API should rather be extended to simplify wrapping
+of existing functionality.
+
+The DType class requires C-side storage of methods and additional information,
+to be implemented by a ``DTypeMeta`` class. Each ``DType`` class is an
+instance of ``DTypeMeta`` with a well-defined and extensible interface;
+end users ignore it.
+
+.. _nep42_hierarchy_figure:
+.. figure:: _static/dtype_hierarchy.svg
+ :figclass: align-center
- np.array(np.array(1, dtype=Categorical)[()])
-requires to pass the original ``dtype=Categorical`` or returns an array
-with dtype ``object``.
-While a general limitation, the round-tripping shall always be possible if
-``dtype=old_dtype`` is provided.
+Miscellaneous methods and attributes
+==============================================================================
+
+This section collects definitions in the DType class that are not used in
+casting and array coercion, which are described in detail below.
+
+* Existing dtype methods and C-side fields are preserved.
+
+* ``DType.type`` replaces ``dtype.type``. Unless a use case arises,
+ ``dtype.type`` will be deprecated.
+ This indicates a Python scalar type which represents the same values as
+ the DType. This is the same type as used in the proposed `Class getter`_
+ and for `DType discovery during array coercion`_.
+ (This can may also be set for abstract DTypes, this is necessary
+ for array coercion.)
+
+* A new ``self.canonical`` property generalizes the notion of byte order to
+ indicate whether data has been stored in a default/canonical way. For
+ existing code, "canonical" will just signify native byte order, but it can
+ take on new meanings in new DTypes -- for instance, to distinguish a
+ complex-conjugated instance of Complex which stores ``real - imag`` instead
+ of ``real + imag`` and is thus not the canonical storage. The ISNBO ("is
+ native byte order") flag might be repurposed as the canonical flag.
+
+* Support is included for parametric DTypes. As explained in
+ :ref:`NEP 40 <parametric-datatype-discussion>`, parametric types have a
+ value associated with them. A DType will be deemed parametric if it
+ inherits from ParametricDType.
+
+ Strings are one example of a parametric type -- ``S8`` is different from
+ ``S4`` because ``S4`` cannot store a length 8 string such as ``"length 8"``
+ while ``S8`` can.
+ Similarly, the ``datetime64`` DType is parametric, since its unit must be specified.
+ The associated ``type`` is the ``np.datetime64`` scalar.
+
+* DType methods may resemble or even reuse existing Python slots. Thus Python
+ special slots are off-limits for user-defined DTypes (for instance, defining
+ ``Unit("m") > Unit("cm")``), since we may want to develop a meaning for these
+ operators that is common to all DTypes.
+
+* Sorting functions are moved to the DType class. They may be implemented by
+ defining a method ``dtype_get_sort_function(self, sortkind="stable") ->
+ sortfunction`` that must return ``NotImplemented`` if the given ``sortkind``
+ is not known.
+
+* Functions that cannot be removed are implemented as special methods.
+ Many of these were previously defined part of the :c:type:`PyArray_ArrFuncs`
+ slot of the dtype instance (``PyArray_Descr *``) and include functions
+ such as ``nonzero``, ``fill`` (used for ``np.arange``), and
+ ``fromstr`` (used to parse text files).
+ These old methods will be deprecated and replacements
+ following the new design principles added.
+ The API is not defined here. Since these methods can be deprecated and renamed
+ replacements added, it is acceptable if these new methods have to be modified.
+
+* Use of ``kind`` for non-built-in types is discouraged in favor of
+ ``isinstance`` checks. ``kind`` will return the ``__qualname__`` of the
+ object to ensure uniqueness for all DTypes. On the C side, ``kind`` and
+ ``char`` are set to ``\0`` (NULL character).
+ While ``kind`` will be discouraged, the current ``np.issubdtype``
+ may remain the preferred method for this type of check.
+
+* A method ``ensure_canonical(self) -> dtype`` returns a new dtype (or
+ ``self``) with the ``canonical`` flag set.
+
+* Since NumPy's approach is to provide functionality through unfuncs,
+ functions like sorting that will be implemented in DTypes might eventually be
+ reimplemented as generalized ufuncs.
+
+.. _casting:
+
+******************************************************************************
+Casting
+******************************************************************************
-**Example:**
+We review here the operations related to casting arrays:
-The current datetime DType requires a ``__discover_descr_from_pyobject__``
-which returns the correct unit for string inputs. This allows it to support
-the current::
+- Finding the "common dtype," currently exposed by ``np.promote_types`` or
+ ``np.result_type``
- np.array(["2020-01-02", "2020-01-02 11:24"], dtype="M8")
+- The result of calling ``np.can_cast``
-By inspecting the date strings. Together with the below common dtype
-operation, this allows it to automatically find that the datetime64 unit
-should be "minutes".
+We show how casting arrays with ``arr.astype(new_dtype)`` will be implemented.
+`Common DType` operations
+==============================================================================
-Common DType Operations
-^^^^^^^^^^^^^^^^^^^^^^^
+Common-type operations are vital for array coercion when input types are
+mixed. They determine the output dtype of ``np.concatenate()`` and are useful
+in themselves.
-NumPy currently provides functions like ``np.result_type`` and
-``np.promote_types`` for determining common types.
+NumPy provides ``np.result_type`` and
+``np.promote_types``.
These differ in that ``np.result_type`` can take arrays and scalars as input
-and implements value based promotion [1]_.
+and implements value-based promotion [1]_.
-To distinguish between the promotion occurring during universal function application,
-we will call it "common type" operation here.
+To distinguish between the promotion occurring during universal function
+application, we will call it "common type" operation here.
**Motivation:**
-Common type operations are vital for array coercion when different
-input types are mixed.
-They also provide the logic currently used to decide the output dtype of
-``np.concatenate()`` and on their own are quite useful.
Furthermore, common type operations may be used to find the correct dtype
to use for functions with different inputs (including universal functions).
@@ -684,32 +460,33 @@ This includes an interesting distinction:
(Hypothetical example:
``float_arr + string_arr -> string``, but the output string length is
not the same as ``np.concatenate(float_arr, string_arr)).dtype``.)
-2. Array coercion and concatenation require the common dtype *instance*.
-**Implementation:**
-The implementation of the common dtype (instance) determination
-has some overlap with casting.
-Casting from a specific dtype (Float64) to a String needs to find
-the correct string length (a step that is mainly necessary for parametric dtypes).
+2. Array coercion and concatenation require the common dtype *instance*.
+
+**Implementation:** The implementation of the common dtype (instance)
+determination has some overlap with casting. Casting from a specific dtype
+(Float64) to a String needs to find the correct string length (a step that is
+mainly necessary for parametric dtypes).
We propose the following implementation:
-1. ``__common_dtype__(cls, other : DTypeMeta) -> DTypeMeta`` answers what the common
- DType class is given two DType class objects.
- It may return ``NotImplemented`` to defer to ``other``.
- (For abstract DTypes, subclasses get precedence, concrete types are always
- leaves, so always get preference or are tried from left to right).
+1. ``__common_dtype__(cls, other : DTypeMeta) -> DTypeMeta`` answers what the
+ common DType class is, given two DType class objects. It may return
+ ``NotImplemented`` to defer to ``other``. (For abstract DTypes, subclasses
+ get precedence, concrete types are never superclasses, so always get preference
+ or are tried from left to right).
+
2. ``__common_instance__(self: SelfT, other : SelfT) -> SelfT`` is used when
two instances of the same DType are given.
- For builtin dtypes (that are not parametric), this
- currently always returns ``self`` (but ensures native byte order).
+ For built-in dtypes (that are not parametric), this
+ currently always returns ``self`` (but ensures canonical representation).
This is to preserve metadata. We can thus provide a default implementation
for non-parametric user dtypes.
These two cases do *not* cover the case where two different dtype instances
-need to be promoted. For example `">float64"` and `"S8"`.
-The solution is partially "outsourced" to the casting machinery by
-splitting the operation up into three steps:
+need to be promoted. For example `">float64"` and `"S8"`. The solution is
+partially "outsourced" to the casting machinery by splitting the operation up
+into three steps:
1. ``Float64.__common_dtype__(type(>float64), type(S8))``
returns `String` (or defers to ``String.__common_dtype__``).
@@ -717,15 +494,13 @@ splitting the operation up into three steps:
to `"S32"` (see below for how casting will be defined).
3. ``String.__common_instance__("S8", "S32")`` returns the final `"S32"`.
-The main reason for this is to avoid the need to implement
-identical functionality multiple times.
-The design (together with casting) naturally separates the concerns of
-different Datatypes.
-In the above example, Float64 does not need to know about the cast.
-While the casting machinery (``CastingImpl[Float64, String]``)
-could include the third step, it is not required to do so and the string
-can always be extended (e.g. with new encodings) without extending the
-``CastingImpl[Float64, String]``.
+The main reason for this is to avoid the need to implement identical
+functionality multiple times. The design (together with casting) naturally
+separates the concerns of different Datatypes. In the above example, Float64
+does not need to know about the cast. While the casting machinery
+(``CastingImpl[Float64, String]``) could include the third step, it is not
+required to do so and the string can always be extended (e.g. with new
+encodings) without extending the ``CastingImpl[Float64, String]``.
This means the implementation will work like this::
@@ -744,7 +519,7 @@ This means the implementation will work like this::
# Find what dtype1 is cast to when cast to the common DType
# by using the CastingImpl as described below:
castingimpl = get_castingimpl(type(dtype1), common)
- safety, (_, dtype1) = castingimpl.adjust_descriptors((dtype1, None))
+ safety, (_, dtype1) = castingimpl.resolve_descriptors((dtype1, None))
assert safety == "safe" # promotion should normally be a safe cast
if type(dtype2) is not common:
@@ -755,12 +530,10 @@ This means the implementation will work like this::
Some of these steps may be optimized for non-parametric DTypes.
-**Note:**
-
-A currently implemented fallback for the ``__common_dtype__`` operation
-is to use the "safe" casting logic.
-Since ``int16`` can safely cast to ``int64``, it is clear that
-``np.promote_types(int16, int64)`` should be ``int64``.
+**Note:** A currently implemented fallback for the ``__common_dtype__``
+operation is to use the "safe" casting logic. Since ``int16`` can safely cast
+to ``int64``, it is clear that ``np.promote_types(int16, int64)`` should be
+``int64``.
However, this cannot define all such operations, and will fail for example for::
@@ -771,39 +544,35 @@ in most cases a safe-cast implies that this will be the result of the
``__common_dtype__`` method.
Note that some exceptions may apply. For example casting ``int32`` to
-a (long enough) string is – at least at this time – considered "safe".
+a (long enough) string is at least at this time considered "safe".
However ``np.promote_types(int32, String)`` will *not* be defined.
-**Alternatives:**
-
-The use of casting for common dtype (instance) determination neatly separates
-the concerns and allows for a minimal set of duplicate functionality
-being implemented.
-In cases of mixed DType (classes), it also adds an additional step
-to finding the common dtype.
-The common dtype (of two instances) could thus be implemented explicitly to avoid
-this indirection, potentially only as a fast-path.
-The above suggestion assumes that this is, however, not a speed relevant path,
-since in most cases, e.g. in array coercion, only a single Python type (and thus
-dtype) is involved.
-The proposed design hinges in the implementation of casting to be
-separated into its own ufunc-like object as described below.
+**Alternatives:** The use of casting for common dtype (instance) determination
+neatly separates the concerns and allows for a minimal set of duplicate
+functionality being implemented. In cases of mixed DType (classes), it also
+adds an additional step to finding the common dtype. The common dtype (of two
+instances) could thus be implemented explicitly to avoid this indirection,
+potentially only as a fast-path. The above suggestion assumes that this is,
+however, not a speed relevant path, since in most cases, e.g. in array
+coercion, only a single Python type (and thus dtype) is involved. The proposed
+design hinges in the implementation of casting to be separated into its own
+ufunc-like object as described below.
In principle common DType could be defined only based on "safe casting" rules,
if we order all DTypes and find the first one both can cast to safely.
However, the issue with this approach is that a newly added DType can change
the behaviour of an existing program. For example, a new ``int24`` would be
-the first valid common type for ``int16`` and ``uint16``, demoting the currently
-defined behaviour of ``int32``.
-This API extension could be allowed in the future, while adding it may be
-more involved, the current proposal for defining casts is fully opaque in
-this regard and thus extensible.
-
-**Example:**
-
-``object`` always chooses ``object`` as the common DType. For ``datetime64``
-type promotion is defined with no other datatype, but if someone were to
-implement a new higher precision datetime, then::
+the first valid common type for ``int16`` and ``uint16``, demoting the
+currently defined behavior of ``int32``.
+Both, the need of a linear type hierarchy and the potential of changing
+existing behaviour by adding a new DType, are a downside to using a generic
+rule based on "safe casting".
+However, a more generic common DType could be implemented in the future, since
+``__common_dtype__`` can in principle use casting information internally.
+
+**Example:** ``object`` always chooses ``object`` as the common DType. For
+``datetime64`` type promotion is defined with no other datatype, but if
+someone were to implement a new higher precision datetime, then::
HighPrecisionDatetime.__common_dtype__(np.dtype[np.datetime64])
@@ -811,33 +580,31 @@ would return ``HighPrecisionDatetime``, and the below casting may need to
decide how to handle the datetime unit.
-Casting
-^^^^^^^
+The cast operation
+==============================================================================
-Maybe the most complex and interesting operation which is provided
-by DTypes is the ability to cast from one dtype to another.
-The casting operation is much like a typical function (universal function) on
-arrays converting one input to a new output.
-There are mainly two distinctions:
+Perhaps the most complex and interesting DType operation is casting. Casting
+is much like a typical universal function on arrays, converting one input to a
+new output. There are two key distinctions:
-1. Casting always requires an explicit output datatype to be given.
-2. The NumPy iterator API requires access to lower-level functions than
- is currently necessary for universal functions.
+1. Casting always requires an explicit output datatype.
+2. The NumPy iterator API requires access to functions that are lower-level
+ than what universal functions currently need.
-Casting from one dtype to another can be complex, and generally a casting
-function may not implement all details of each input datatype (such as
-non-native byte order or unaligned access).
-Thus casting naturally is performed in up to three steps:
+Casting can be complex, and may not implement all details of each input
+datatype (such as non-native byte order or unaligned access). Thus casting
+naturally is performed in up to three steps:
-1. The input datatype is normalized and prepared for the actual cast.
+1. The given datatype is normalized and prepared for the actual cast.
2. The cast is performed.
3. The cast result, which is in a normalized form, is cast to the requested
form (non-native byte order).
-although often only step 2. is required.
+Often only step 2 is required.
Further, NumPy provides different casting kinds or safety specifiers:
+* "equivalent"
* "safe"
* "same_kind"
* "unsafe"
@@ -845,66 +612,63 @@ Further, NumPy provides different casting kinds or safety specifiers:
and in some cases a cast may even be represented as a simple view.
-**Motivation:**
-
-Similar to the common dtype/DType operation above, we again have two use cases:
+**Motivation:** Similar to the common dtype/DType operation above, we again
+have two use cases:
1. ``arr.astype(np.String)`` (current spelling ``arr.astype("S")``)
-2. ``arr.astype(np.dtype("S8"))``.
+2. ``arr.astype(np.dtype("S8"))``
-Where the first case is also noted in NEP 40 and 41 as a design goal, since
+where the first case is also noted in NEP 40 and 41 as a design goal, since
``np.String`` could also be an abstract DType as mentioned above.
The implementation of casting should also come with as little duplicate
-implementation as necessary, i.e. to avoid unnecessary methods on the
-DTypes.
+implementation as necessary, i.e. to avoid unnecessary methods on the DTypes.
Furthermore, it is desirable that casting is implemented similar to universal
functions.
Analogous to the above, the following also need to be defined:
1. ``np.can_cast(dtype, DType, "safe")`` (instance to class)
-2. ``np.can_cast(dtype, other_dtype, "safe")`` (casting an instance to another instance)
+2. ``np.can_cast(dtype, other_dtype, "safe")`` (casting an instance to another
+ instance)
-overloading the meaning of ``dtype`` to mean either class or instance
-(on the Python level).
-The question of ``np.can_cast(DType, OtherDType, "safe")`` is also a
-possibility and may be used internally.
-However, it is initially not necessary to expose to Python.
+overloading the meaning of ``dtype`` to mean either class or instance (on the
+Python level). The question of ``np.can_cast(DType, OtherDType, "safe")`` is
+also a possibility and may be used internally. However, it is initially not
+necessary to expose to Python.
-**Implementation:**
-
-During DType creation, DTypes will have the ability to pass a list of
-``CastingImpl`` objects, which can define casting to and from the DType.
-One of these ``CastingImpl`` objects is special because it should define
-the cast within the same DType (from one instance to another).
-A DType which does not define this, must have only a single implementation
-and not be parametric.
+**Implementation:** During DType creation, DTypes will have the ability to
+pass a list of ``CastingImpl`` objects, which can define casting to and from
+the DType. One of these ``CastingImpl`` objects is special because it should
+define the cast within the same DType (from one instance to another). A DType
+which does not define this, must have only a single implementation and not be
+parametric.
Each ``CastingImpl`` has a specific DType signature:
-``CastingImpl[InputDtype, RequestedDtype]``.
-And implements the following methods and attributes:
+``CastingImpl[InputDtype, RequestedDtype]``
+and implements the following methods and attributes:
-* ``adjust_descriptors(self, Tuple[DType] : input) -> casting, Tuple[DType]``.
+* ``resolve_descriptors(self, Tuple[DType] : input) -> casting, Tuple[DType]``.
Here ``casting`` signals the casting safeness (safe, unsafe, or same-kind)
and the output dtype tuple is used for more multi-step casting (see below).
* ``get_transferfunction(...) -> function handling cast`` (signature to be decided).
This function returns a low-level implementation of a strided casting function
("transfer function").
-* ``cast_kind`` attribute with one of safe, unsafe, or same-kind. Used to
+* ``casting`` attribute with one of equivalent, safe, unsafe, or same-kind. Used to
quickly decide casting safety when this is relevant.
-``adjust_descriptors`` provides information about whether or
+``resolve_descriptors`` provides information about whether or
not a cast is safe and is of importance mainly for parametric DTypes.
``get_transferfunction`` provides NumPy with a function capable of performing
the actual cast. Initially the implementation of ``get_transferfunction``
-will be *private*, and users will only be able to provide contiguous loops
+will be *private*, and users will only be able to provide strided loops
with the signature.
-**Performing the Cast:**
+**Performing the cast**
.. _cast_figure:
+
.. figure:: _static/casting_flow.svg
:figclass: align-center
@@ -916,141 +680,116 @@ an ``int24`` to an ``S8`` string (which can hold all 24bit integers).
Due to this limited implementation, the full cast has to do multiple
conversions. The full process is:
-1. Call ``CastingImpl[Int24, String].adjust_descriptors((int24, "S20"))``.
+1. Call ``CastingImpl[Int24, String].resolve_descriptors((int24, "S20"))``.
This provides the information that ``CastingImpl[Int24, String]`` only
- implements the cast of ``int24`` to ``"S8``.
+ implements the cast of ``int24`` to ``"S8"``.
2. Since ``"S8"`` does not match ``"S20"``, use
``CastingImpl[String, String].get_transferfunction()``
to find the transfer (casting) function to convert an ``"S8"`` into an ``"S20"``
3. Fetch the transfer function to convert an ``int24`` to an ``"S8"`` using
``CastingImpl[Int24, String].get_transferfunction()``
4. Perform the actual cast using the two transfer functions:
- ``int24(42) -> S8("42") -> S20("42")``.
+ ``int24(42) -> S8("42") -> S20("42")``.
-Note that in this example the ``adjust_descriptors`` function plays a less
+Note that in this example the ``resolve_descriptors`` function plays a less
central role. It becomes more important for ``np.can_cast``.
-Further, ``adjust_descriptors`` allows the implementation for
+Further, ``resolve_descriptors`` allows the implementation for
``np.array(42, dtype=int24).astype(String)`` to call
-``CastingImpl[Int24, String].adjust_descriptors((int24, None))``.
+``CastingImpl[Int24, String].resolve_descriptors((int24, None))``.
In this case the result of ``(int24, "S8")`` defines the correct cast:
``np.array(42, dtype=int24),astype(String) == np.array("42", dtype="S8")``.
-**Casting Safety:**
+**Casting safety**
-To answer the question of casting safety
-``np.can_cast(int24, "S20", casting="safe")``, only the ``adjust_descriptors``
-function is required and called is in the same way as in
-`the figure describing a cast <cast_figure>`_.
-In this case, the calls to ``adjust_descriptors``, will also provide the
-information that ``int24 -> "S8"`` as well as ``"S8" -> "S20"`` are safe casts,
-and thus also the ``int24 -> "S20"`` is a safe cast.
+To answer the question of casting safety ``np.can_cast(int24, "S20",
+casting="safe")``, only the ``resolve_descriptors`` function is required and
+is called in the same way as in `the figure describing a cast <cast_figure>`_.
+In this case, the calls to ``resolve_descriptors``, will also provide the
+information that ``int24 -> "S8"`` as well as ``"S8" -> "S20"`` are safe
+casts, and thus also the ``int24 -> "S20"`` is a safe cast.
-The casting safety can currently be "equivalent" when a cast is both safe
-and can be performed using only a view.
-The information that a cast is a simple "view" will instead be handled by
-an additional flag. Thus the ``casting`` can have the 6 values in total:
-safe, unsafe, same-kind as well as safe+view, unsafe+view, same-kind+view.
-Where the current "equivalent" is the same as safe+view.
+In some cases, no cast is necessary. For example, on most Linux systems
+``np.dtype("long")`` and ``np.dtype("longlong")`` are different dtypes but are
+both 64bit integers.
+In this case, the cast can be performed using ``long_arr.view("longlong")``.
+The information that a cast is a
+"view" will be handled by an additional flag. Thus the ``casting``
+can have the 8 values in total: equivalent, safe, unsafe, same-kind as well as equivalent+view, safe+view,
+unsafe+view, and same-kind+view.
+NumPy currently defines ``dtype1 == dtype2`` to be True only if byte order matches.
+This functionality can be replaced with the combination of "equivalent" casting
+and the "view" flag.
-(For more information on the ``adjust_descriptor`` signature see the
-C-API section below.)
+(For more information on the ``resolve_descriptors`` signature see the C-API
+section below and NEP 43.)
-**Casting between instances of the same DType:**
+**Casting between instances of the same DType**
-In general one of the casting implementations define by the DType implementor
+In general one of the casting implementations defined by the DType implementor
must be ``CastingImpl[DType, DType]`` (unless there is only a singleton
-instance).
-To keep the casting to as few steps as possible, this implementation must
-be capable any conversions between all instances of this DType.
+instance). To keep the casting to as few steps as possible, this
+implementation must initially be capable of any conversions between all instances of this
+DType.
-**General Multi-Step Casting**
+**General multistep casting**
In general we could implement certain casts, such as ``int8`` to ``int24``
-even if the user only provides an ``int16 -> int24`` cast.
-This proposal currently does not provide this functionality. However,
-it could be extended in the future to either find such casts dynamically,
-or at least allow ``adjust_descriptors`` to return arbitrary ``dtypes``.
-If ``CastingImpl[Int8, Int24].adjust_descriptors((int8, int24))`` returns
-``(int16, int24)``, the actual casting process could be extended to include
-the ``int8 -> int16`` cast. Unlike the above example, which is limited
-to at most three steps.
-
-
-**Alternatives:**
-
-The choice of using only the DType classes in the first step of finding the
-correct ``CastingImpl`` means that the default implementation of
-``__common_dtype__`` has a reasonable definition of "safe casting" between
+even if the user only provides an ``int16 -> int24`` cast. This proposal
+currently does not provide this functionality. However, it could be extended
+in the future to either find such casts dynamically, or at least allow
+``resolve_descriptors`` to return arbitrary ``dtypes``. If ``CastingImpl[Int8,
+Int24].resolve_descriptors((int8, int24))`` returns ``(int16, int24)``, the
+actual casting process could be extended to include the ``int8 -> int16``
+cast. This adds an additional step to the casting process.
+
+
+**Alternatives:** The choice of using only the DType classes in the first step
+of finding the correct ``CastingImpl`` means that the default implementation
+of ``__common_dtype__`` has a reasonable definition of "safe casting" between
DTypes classes (although e.g. the concatenate operation using it may still
fail when attempting to find the actual common instance or cast).
-The split into multiple steps may seem to add complexity
-rather than reduce it, however, it consolidates that we have the two distinct
-signatures of ``np.can_cast(dtype, DTypeClass)`` and ``np.can_cast(dtype, other_dtype)``.
+The split into multiple steps may seem to add complexity rather than reduce
+it, however, it consolidates that we have the two distinct signatures of
+``np.can_cast(dtype, DTypeClass)`` and ``np.can_cast(dtype, other_dtype)``.
Further, the above API guarantees the separation of concerns for user DTypes.
-The user ``Int24`` dtype does not have to handle all string lengths if it
-does not wish to do so. Further, if an encoding was added to the ``String``
-DType, this does not affect the overall cast.
-The ``adjust_descriptor`` function can keep returning the default encoding
-and the ``CastingImpl[String, String]`` can take care of any necessary encoding
-changes.
+The user ``Int24`` dtype does not have to handle all string lengths if it does
+not wish to do so. Further, if an encoding was added to the ``String`` DType,
+this does not affect the overall cast. The ``resolve_descriptors`` function can
+keep returning the default encoding and the ``CastingImpl[String, String]``
+can take care of any necessary encoding changes.
The main alternative to the proposed design is to move most of the information
-which is here pushed into the ``CastingImpl`` directly into methods
-on the DTypes. This, however, will not allow the close similarity between casting
-and universal functions. On the up side, it reduces the necessary indirection
-as noted below.
-
-An initial proposal defined two methods ``__can_cast_to__(self, other)``
-to dynamically return ``CastingImpl``.
-The advantage of this addition is that it removes the requirement to know all
-possible casts at DType creation time (of one of the involved DTypes).
-Such API could be added at a later time. It should be noted, however,
-that it would be mainly useful for inheritance-like logic, which can be
-problematic. As an example two different ``Float64WithUnit`` implementations
-both could infer that they can unsafely cast between one another when in fact
-some combinations should cast safely or preserve the Unit (both of which the
-"base" ``Float64`` would discard).
-In the proposed implementation this is not possible, since the two implementations
-are not aware of each other.
-
-
-**Notes:**
-
-The proposed ``CastingImpl`` is designed to be compatible with the
-``UFuncImpl`` proposed in NEP 43.
-While initially it will be a distinct object or C-struct, the aim is that
-``CastingImpl`` can be a subclass or extension of ``UFuncImpl``.
-Once this happens, this may naturally allow the use of a ``CastingImpl`` to
-pass around a specialized casting function directly.
-
-In the future, we may consider adding a way to spell out that specific
-casts are known to be *not* possible.
-
-In the above text ``CastingImpl`` is described as a Python object. In practice,
-the current plan is to implement it as a C-side structure stored on the ``from``
-datatype.
-A Python side API to get an equivalent ``CastingImpl`` object will be created,
-but storing it (similar to the current implementation) on the ``from`` datatype
-avoids the creation of cyclic reference counts.
-
-The way dispatching works for ``CastingImpl`` is planned to be limited initially
-and fully opaque.
-In the future, it may or may not be moved into a special UFunc, or behave
-more like a universal function.
-
-
-**Example:**
-
-The implementation for casting integers to datetime would currently generally
-say that this cast is unsafe (it is always an unsafe cast).
-Its ``adjust_descriptors`` functions may look like::
-
- def adjust_descriptors(input):
- from_dtype, to_dtype = input
+which is here pushed into the ``CastingImpl`` directly into methods on the
+DTypes. This, however, will not allow the close similarity between casting and
+universal functions. On the up side, it reduces the necessary indirection as
+noted below.
+
+An initial proposal defined two methods ``__can_cast_to__(self, other)`` to
+dynamically return ``CastingImpl``. The advantage of this addition is that it
+removes the requirement to define all possible casts at DType creation time (of
+one of the involved DTypes).
+Such API could be added at a later time. This is similar to Python which
+provides ``__getattr__`` for additional control over attribute lookup.
+
+**Notes:** The proposed ``CastingImpl`` is designed to be identical to the
+``PyArrayMethod`` proposed in NEP 43 as part of restructuring ufuncs to handle
+new DTypes.
+
+The way dispatching works for ``CastingImpl`` is planned to be limited
+initially and fully opaque. In the future, it may or may not be moved into a
+special UFunc, or behave more like a universal function.
+
+
+**Example:** The implementation for casting integers to datetime would generally
+say that this cast is unsafe (because it is always an unsafe cast).
+Its ``resolve_descriptors`` function may look like::
+
+ def resolve_descriptors(self, given_dtypes):
+ from_dtype, to_dtype = given_dtypes
from_dtype = from_dtype.ensure_canonical() # ensure not byte-swapped
if to_dtype is None:
@@ -1065,26 +804,384 @@ Its ``adjust_descriptors`` functions may look like::
.. note::
- While NumPy currently defines some of these casts, with the possible
- exception of the unit-less ``timedelta64`` it may be better to not
- define these cast at all. In general we expect that user defined
- DTypes will be using other methods such as ``unit.drop_unit(arr)``
- or ``arr * unit.seconds``.
+ While NumPy currently defines integer to datetime casts, with the possible
+ exception of the unit-less ``timedelta64`` it may be better to not define
+ these casts at all. In general we expect that user defined DTypes will be
+ using custom methods such as ``unit.drop_unit(arr)`` or ``arr *
+ unit.seconds``.
+
+
+******************************************************************************
+Array coercion
+******************************************************************************
+
+The following sections discuss the two aspects related to creating an array from
+arbitrary python objects. This requires a defined protocol to store data
+inside the array. Further, it requires the ability to find the correct dtype
+when a user does not provide the dtype explicitly.
+
+Coercion to and from Python objects
+==============================================================================
+
+**Motivation:** When storing a single value in an array or taking it out, it
+is necessary to coerce (convert) it to and from the low-level representation
+inside the array.
+
+**Description:** Coercing to and from Python scalars requires two to three
+methods:
+
+1. ``__dtype_setitem__(self, item_pointer, value)``
+2. ``__dtype_getitem__(self, item_pointer, base_obj) -> object``;
+ ``base_obj`` is for memory management and usually ignored; it points to
+ an object owning the data. Its only role is to support structured datatypes
+ with subarrays within NumPy, which currently return views into the array.
+ The function returns an equivalent Python scalar (i.e. typically a NumPy
+ scalar).
+3. ``__dtype_get_pyitem__(self, item_pointer, base_obj) -> object`` (initially
+ hidden for new-style user-defined datatypes, may be exposed on user
+ request). This corresponds to the ``arr.item()`` method also used by
+ ``arr.tolist()`` and returns Python floats, for example, instead of NumPy
+ floats.
+
+(The above is meant for C-API. A Python-side API would have to use byte
+buffers or similar to implement this, which may be useful for prototyping.)
+
+These largely correspond to the current definitions. When a certain scalar
+has a known (different) dtype, NumPy may in the future use casting instead of
+``__dtype_setitem__``. A user datatype is (initially) expected to implement
+``__dtype_setitem__`` for its own ``DType.type`` and all basic Python scalars
+it wishes to support (e.g. ``int`` and ``float``). In the future a
+function "``known_scalartype``" may be made public to allow a user dtype to signal
+which Python scalars it can store directly.
+
+
+**Implementation:** The pseudocode implementation for setting a single item in
+an array from an arbitrary Python object ``value`` is (note that some
+functions are only defined below)::
+
+ def PyArray_Pack(dtype, item_pointer, value):
+ DType = type(dtype)
+ if DType.type is type(value) or DType.known_scalartype(type(value)):
+ return dtype.__dtype_setitem__(item_pointer, value)
+
+ # The dtype cannot handle the value, so try casting:
+ arr = np.array(value)
+ if arr.dtype is object or arr.ndim != 0:
+ # not a numpy or user scalar; try using the dtype after all:
+ return dtype.__dtype_setitem__(item_pointer, value)
+
+ arr.astype(dtype)
+ item_pointer.write(arr[()])
+
+where the call to ``np.array()`` represents the dtype discovery and is
+not actually performed.
+
+**Example:** Current ``datetime64`` returns ``np.datetime64`` scalars and can
+be assigned from ``np.datetime64``. However, the datetime
+``__dtype_setitem__`` also allows assignment from date strings ("2016-05-01")
+or Python integers. Additionally the datetime ``__dtype_get_pyitem__``
+function actually returns a Python ``datetime.datetime`` object (most of the
+time).
+
+
+**Alternatives:** This functionality could also be implemented as a cast to and
+from the ``object`` dtype.
+However, coercion is slightly more complex than typical casts.
+One reason is that in general a Python object could itself be a
+zero-dimensional array or scalar with an associated DType.
+Such an object has a DType, and the correct cast to another DType is already
+defined::
+
+ np.array(np.float32(4), dtype=object).astype(np.float64)
+
+is identical to::
+
+ np.array(4, dtype=np.float32).astype(np.float64)
+
+Implementing the first ``object`` to ``np.float64`` cast explicitly,
+would require the user to take to duplicate or fall back to existing
+casting functionality.
+
+It is certainly possible to describe the coercion to and from Python objects
+using the general casting machinery,
+but the ``object`` dtype is special and important enough to be handled by NumPy
+using the presented methods.
+
+**Further Issues and Discussion:** The ``__dtype_setitem__`` function currently duplicates
+some code, such as coercion from a string. ``datetime64`` allows assignment
+from string, but the same conversion also occurs for casting from the string
+dtype to ``datetime64``. In the future, we may expose the ``known_scalartype``
+function to allow the user to implement such duplication.
+For example, NumPy would normally use ``np.array(np.string_("2019")).astype(datetime64)``,
+but ``datetime64`` could choose to use its ``__dtype_setitem__`` instead,
+e.g. for performance reasons.
+
+There is an issue about how subclasses of scalars should be handled.
+We anticipate to stop automatically detecting the dtype for
+``np.array(float64_subclass)`` to be float64.
+The user can still provide ``dtype=np.float64``.
+However, the above automatic casting using ``np.array(scalar_subclass).astype(requested_dtype)``
+will fail.
+In many cases, this is not an issue, since the Python ``__float__`` protocol
+can be used instead. But in some cases, this will mean that subclasses of
+Python scalars will behave differently.
+
+.. note::
+
+ *Example:* ``np.complex256`` should not use ``__float__`` in its
+ ``__dtype_setitem__`` method in the future unless it is a known floating
+ point type. If the scalar is a subclass of a different high precision
+ floating point type (e.g. ``np.float128``) then this currently loses
+ precision without notifying the user.
+ In that case ``np.array(float128_subclass(3), dtype=np.complex256)``
+ may fail unless the ``float128_subclass`` is first converted to the
+ ``np.float128`` base class.
+
+
+DType discovery during array coercion
+==============================================================================
+
+An important step in the use of NumPy arrays is creation of the array
+from collections of generic Python objects.
+
+**Motivation:** Although the distinction is not clear currently, there are two main needs::
+
+ np.array([1, 2, 3, 4.])
+
+needs to guess the correct dtype based on the Python objects inside.
+Such an array may include a mix of datatypes, as long as they can be
+promoted.
+A second use case is when users provide the output DType class, but not the
+specific DType instance::
+
+ np.array([object(), None], dtype=np.dtype[np.string_]) # (or `dtype="S"`)
+
+In this case the user indicates that ``object()`` and ``None`` should be
+interpreted as strings.
+The need to consider the user provided DType also arises for a future
+``Categorical``::
+
+ np.array([1, 2, 1, 1, 2], dtype=Categorical)
+
+which must interpret the numbers as unique categorical values rather than
+integers.
+
+There are three further issues to consider:
+
+1. It may be desirable to create datatypes associated
+ with normal Python scalars (such as ``datetime.datetime``) that do not
+ have a ``dtype`` attribute already.
+2. In general, a datatype could represent a sequence, however, NumPy currently
+ assumes that sequences are always collections of elements
+ (the sequence cannot be an element itself).
+ An example would be a ``vector`` DType.
+3. An array may itself contain arrays with a specific dtype (even
+ general Python objects). For example:
+ ``np.array([np.array(None, dtype=object)], dtype=np.String)``
+ poses the issue of how to handle the included array.
+
+Some of these difficulties arise because finding the correct shape
+of the output array and finding the correct datatype are closely related.
+
+**Implementation:** There are two distinct cases above:
+
+1. The user has provided no dtype information.
+2. The user provided a DType class -- as represented, for example, by ``"S"``
+ representing a string of any length.
+
+In the first case, it is necessary to establish a mapping from the Python type(s)
+of the constituent elements to the DType class.
+Once the DType class is known, the correct dtype instance needs to be found.
+In the case of strings, this requires to find the string length.
+
+These two cases shall be implemented by leveraging two pieces of information:
+
+1. ``DType.type``: The current type attribute to indicate which Python scalar
+ type is associated with the DType class (this is a *class* attribute that always
+ exists for any datatype and is not limited to array coercion).
+2. ``__discover_descr_from_pyobject__(cls, obj) -> dtype``: A classmethod that
+ returns the correct descriptor given the input object.
+ Note that only parametric DTypes have to implement this.
+ For non-parametric DTypes using the default instance will always be acceptable.
+
+The Python scalar type which is already associated with a DType through the
+``DType.type`` attribute maps from the DType to the Python scalar type.
+At registration time, a DType may choose to allow automatically discover for
+this Python scalar type.
+This requires a lookup in the opposite direction, which will be implemented
+using global a mapping (dictionary-like) of::
+
+ known_python_types[type] = DType
+
+Correct garbage collection requires additional care.
+If both the Python scalar type (``pytype``) and ``DType`` are created dynamically,
+they will potentially be deleted again.
+To allow this, it must be possible to make the above mapping weak.
+This requires that the ``pytype`` holds a reference of ``DType`` explicitly.
+Thus, in addition to building the global mapping, NumPy will store the ``DType`` as
+``pytype.__associated_array_dtype__`` in the Python type.
+This does *not* define the mapping and should *not* be accessed directly.
+In particular potential inheritance of the attribute does not mean that NumPy will use the
+superclasses ``DType`` automatically. A new ``DType`` must be created for the
+subclass.
+
+.. note::
+
+ Python integers do not have a clear/concrete NumPy type associated right
+ now. This is because during array coercion NumPy currently finds the first
+ type capable of representing their value in the list of `long`, `unsigned
+ long`, `int64`, `unsigned int64`, and `object` (on many machines `long` is
+ 64 bit).
+
+ Instead they will need to be implemented using an ``AbstractPyInt``. This
+ DType class can then provide ``__discover_descr_from_pyobject__`` and
+ return the actual dtype which is e.g. ``np.dtype("int64")``. For
+ dispatching/promotion in ufuncs, it will also be necessary to dynamically
+ create ``AbstractPyInt[value]`` classes (creation can be cached), so that
+ they can provide the current value based promotion functionality provided
+ by ``np.result_type(python_integer, array)`` [1]_.
+
+To allow for a DType to accept inputs as scalars that are not basic Python
+types or instances of ``DType.type``, we use ``known_scalar_type`` method.
+This can allow discovery of a ``vector`` as a scalar (element) instead of a sequence
+(for the command ``np.array(vector, dtype=VectorDType)``) even when ``vector`` is itself a
+sequence or even an array subclass. This will *not* be public API initially,
+but may be made public at a later time.
+
+**Example:** The current datetime DType requires a
+``__discover_descr_from_pyobject__`` which returns the correct unit for string
+inputs. This allows it to support::
+
+ np.array(["2020-01-02", "2020-01-02 11:24"], dtype="M8")
+
+By inspecting the date strings. Together with the common dtype
+operation, this allows it to automatically find that the datetime64 unit
+should be "minutes".
+
+
+**NumPy Internal Implementation:** The implementation to find the correct dtype
+will work similar to the following pseudocode::
+
+ def find_dtype(array_like):
+ common_dtype = None
+ for element in array_like:
+ # default to object dtype, if unknown
+ DType = known_python_types.get(type(element), np.dtype[object])
+ dtype = DType.__discover_descr_from_pyobject__(element)
+
+ if common_dtype is None:
+ common_dtype = dtype
+ else:
+ common_dtype = np.promote_types(common_dtype, dtype)
+
+In practice, the input to ``np.array()`` is a mix of sequences and array-like
+objects, so that deciding what is an element requires to check whether it
+is a sequence.
+The full algorithm (without user provided dtypes) thus looks more like::
+
+ def find_dtype_recursive(array_like, dtype=None):
+ """
+ Recursively find the dtype for a nested sequences (arrays are not
+ supported here).
+ """
+ DType = known_python_types.get(type(element), None)
+
+ if DType is None and is_array_like(array_like):
+ # Code for a sequence, an array_like may have a DType we
+ # can use directly:
+ for element in array_like:
+ dtype = find_dtype_recursive(element, dtype=dtype)
+ return dtype
+
+ elif DType is None:
+ DType = np.dtype[object]
+
+ # dtype discovery and promotion as in `find_dtype` above
+
+If the user provides ``DType``, then this DType will be tried first, and the
+``dtype`` may need to be cast before the promotion is performed.
+
+**Limitations:** The motivational point 3. of a nested array
+``np.array([np.array(None, dtype=object)], dtype=np.String)`` is currently
+(sometimes) supported by inspecting all elements of the nested array.
+User DTypes will implicitly handle these correctly if the nested array
+is of ``object`` dtype.
+In some other cases NumPy will retain backward compatibility for existing
+functionality only.
+NumPy uses such functionality to allow code such as::
+
+ >>> np.array([np.array(["2020-05-05"], dtype="S")], dtype=np.datetime64)
+ array([['2020-05-05']], dtype='datetime64[D]')
+
+which discovers the datetime unit ``D`` (days).
+This possibility will not be accessible to user DTypes without an
+intermediate cast to ``object`` or a custom function.
+
+The use of a global type map means that an error or warning has to be given if
+two DTypes wish to map to the same Python type. In most cases user DTypes
+should only be implemented for types defined within the same library to avoid
+the potential for conflicts. It will be the DType implementor's responsibility
+to be careful about this and use avoid registration when in doubt.
+
+**Alternatives:** Instead of a global mapping, we could rely on the scalar
+attribute ``scalar.__associated_array_dtype__``.
+This only creates a difference in behaviour for subclasses and the exact
+implementation can be undefined initially.
+Scalars will be expected to derive from a NumPy scalar.
+In principle NumPy could, for a time, still choose to rely on the attribute.
+
+An earlier proposal for the ``dtype`` discovery algorithm,
+was to use a two-pass approach.
+First finding only the correct ``DType`` class and only then discovering the parametric
+``dtype`` instance.
+This was rejected for unnecessary complexity.
+The main advantage of this method is that it would have enabled value
+based promotion in universal functions, allowing::
+
+ np.add(np.array([8], dtype="uint8"), [4])
+
+to return a ``uint8`` result (instead of ``int16``), which currently happens for::
+
+ np.add(np.array([8], dtype="uint8"), 4)
+(note the list ``[4]`` instead of scalar ``4``).
+This is not a feature NumPy currently has or desires to support.
-C-Side API
-^^^^^^^^^^
+**Further Issues and Discussion:** It is possible to create a DType
+such as Categorical, array, or vector which can only be used if ``dtype=DType``
+is provided. Such DTypes cannot roundtrip correctly. For example::
+
+ np.array(np.array(1, dtype=Categorical)[()])
+
+will result in an integer array. To get the original ``Categorical`` array
+``dtype=Categorical`` will need to be passed explicitly.
+This is a general limitation, but round-tripping is always possible if
+``dtype=original_arr.dtype`` is passed.
+
+
+.. _c-api:
+
+******************************************************************************
+Public C-API
+******************************************************************************
A Python side API shall not be defined here. This is a general side approach.
DType creation
-""""""""""""""
+==============================================================================
+
+To create a new DType the user will need to define all the methods and
+attributes as presented above and outlined in the `Usage and impact`_
+section.
+Some additional methods similar to those currently defined as part of
+:c:type:`PyArray_ArrFuncs` will be necessary and part of the slots struct
+below.
-As already mentioned in NEP 41, the interface to define new DTypes in C
-is modeled after the limited API in Python: the above-mentioned slots
-and some additional necessary information will thus be passed within a slots
-struct and identified by ``ssize_t`` integers::
+As already mentioned in NEP 41, the interface to define this DType class in C is
+modeled after the `Python limited API <https://www.python.org/dev/peps/pep-0384/>`_:
+the above-mentioned slots and some additional necessary information will
+thus be passed within a slots struct and identified by ``ssize_t`` integers::
static struct PyArrayMethodDef slots[] = {
{NPY_dt_method, method_implementation},
@@ -1093,10 +1190,8 @@ struct and identified by ``ssize_t`` integers::
}
typedef struct{
- PyTypeObject *typeobj; /* type of python scalar */
- int is_parametric; /* Is the dtype parametric? */
- int is_abstract; /* Is the dtype abstract? */
- int flags /* flags (to be discussed) */
+ PyTypeObject *typeobj; /* type of python scalar or NULL */
+ int flags /* flags, including parametric and abstract */
/* NULL terminated CastingImpl; is copied and references are stolen */
CastingImpl *castingimpls[];
PyType_Slot *slots;
@@ -1105,20 +1200,19 @@ struct and identified by ``ssize_t`` integers::
PyObject* PyArray_InitDTypeMetaFromSpec(PyArrayDTypeMeta_Spec *dtype_spec);
-all of this information will be copied during instantiation.
+All of this information will be copied.
-**TODO:** The DType author should be able to at define new methods for
-their DType, up to defining a full type object and in the future possibly even
-extending the ``PyArrayDTypeMeta_Type`` struct.
-We have to decide on how (and what) to make available to the user initially.
-A proposed initial solution may be to simply allow inheriting from an existing
-class.
-Further this prevents overriding some slots, such as `==` which may not be
-desirable.
+**TODO:** The DType author should be able to define new methods for their
+DType, up to defining a full type object and in the future possibly even
+extending the ``PyArrayDTypeMeta_Type`` struct. We have to decide on how (and
+what) to make available to the user initially. A possible initial solution may
+be to only allow inheriting from an existing class: ``class MyDType(np.dtype,
+MyBaseclass)``. If ``np.dtype`` is first in the method resolution order, this
+also prevents overriding some slots, such as ``==`` which may not be desirable.
-The proposed method slots are (prepended with ``NPY_dt_``), these are
-detailed above and given here for summary:
+The ``slots`` will be identified by names which are prefixed with ``NPY_dt_``
+and are:
* ``is_canonical(self) -> {0, 1}``
* ``ensure_canonical(self) -> dtype``
@@ -1129,205 +1223,142 @@ detailed above and given here for summary:
* ``common_dtype(cls, other) -> DType, NotImplemented, or NULL``
* ``common_instance(self, other) -> dtype or NULL``
-If not set, most slots are filled with slots which either error or defer automatically.
+Where possible, a default implementation will be provided if the slot is
+ommitted or set to ``NULL``.
Non-parametric dtypes do not have to implement:
* ``discover_descr_from_pyobject`` (uses ``default_descr`` instead)
* ``common_instance`` (uses ``default_descr`` instead)
-* ``ensure_canonical`` (uses ``default_descr`` instead)
-
-Which will be correct for most dtypes *which do not store metadata*.
-
-Other slots may be replaced by convenience versions, e.g. sorting methods
-can be defined by providing:
+* ``ensure_canonical`` (uses ``default_descr`` instead).
-* ``compare(self, char *item_ptr1, char *item_ptr2, int *res) -> {-1, 0}``
- *TODO: We would like an error return, is this reasonable? (similar to old
- python compare)*
-
-which uses generic sorting functionality. In general, we could add a
-functions such as:
+Sorting is expected to be implemented using:
* ``get_sort_function(self, NPY_SORTKIND sort_kind) -> {out_sortfunction, NotImplemented, NULL}``.
- If the sortkind is not understood it may be allowed to return ``NotImplemented``.
-in the future. However, for example sorting is likely better solved by the
-implementation of multiple generalized ufuncs which are called internally.
+Although for convenience, it will be sufficient if the user implements only:
+
+* ``compare(self, char *item_ptr1, char *item_ptr2, int *res) -> {-1, 0, 1}``
-**Limitations:**
-Using the above ``PyArrayDTypeMeta_Spec`` struct, the structure itself can
-only be extended clumsily (e.g. by adding a version tag to the ``slots``
-to indicate a new, longer version of the struct).
-We could also provide the struct using a function, which however will require
-memory management but would allow ABI-compatible extension
-(the struct is freed again when the DType is created).
+**Limitations:** Using the above ``PyArrayDTypeMeta_Spec`` struct, the
+structure itself can only be extended clumsily (e.g. by adding a version tag
+to the ``slots`` to indicate a new, longer version of the struct). We could
+also provide the struct using a function, which however will require memory
+management but would allow ABI-compatible extension (the struct is freed again
+when the DType is created).
CastingImpl
-"""""""""""
+==============================================================================
The external API for ``CastingImpl`` will be limited initially to defining:
-* ``cast_kind`` attribute, which can be one of the supported casting kinds.
+* ``casting`` attribute, which can be one of the supported casting kinds.
This is the safest cast possible. For example casting between two NumPy
strings is of course "safe" in general, but may be "same kind" in a specific
instance if the second string is shorter. If neither type is parametric the
- ``adjust_descriptors`` must use it.
-* ``adjust_descriptors(dtypes_in[2], dtypes_out[2], casting_out) -> int {0, -1}``
- The out dtypes must be set correctly to dtypes which the strided loop
- (transfer function) can handle. Initially the result must have be instances
- of the same DType class as the ``CastingImpl`` is defined for.
- The ``casting_out`` will be set to ``NPY_SAFE_CASTING``, ``NPY_UNSAFE_CASTING``,
- or ``NPY_SAME_KIND_CASTING``. With a new, additional, flag ``NPY_CAST_IS_VIEW``
- which can be set to indicate that no cast is necessary, but a simple view
- is sufficient to perform the cast.
- The cast should return ``-1`` when a custom error message is set and
- ``NPY_NO_CASTING`` to indicate that a generic casting error should be
- set (this is in most cases preferable).
-* ``strided_loop(char **args, npy_intp *dimensions, npy_intp *strides, dtypes[2]) -> int {0, nonzero}`` (must currently succeed)
-
-This is identical to the proposed API for ufuncs. By default the two dtypes
-are passed in as the last argument. On error return (if no error is set) a
-generic error will be given.
-More optimized loops are in use internally, and will be made available to users
-in the future (see notes)
-The iterator API does not currently support casting errors: this is
-a bug that needs to be fixed. Until it is fixed the loop should always
-succeed (return 0).
-
-Although verbose, the API shall mimic the one for creating a new DType.
-The ``PyArrayCastingImpl_Spec`` will include a field for ``dtypes`` and
-identical to a ``PyArrayUFuncImpl_Spec``::
+ ``resolve_descriptors`` must use it.
+
+* ``resolve_descriptors(self, given_descrs[2], loop_descrs[2]) -> int {casting, -1}``:
+ The ``loop_descrs`` must be set correctly to dtypes which the strided loop
+ (transfer function) can handle. Initially the result must have instances
+ of the same DType class as the ``CastingImpl`` is defined for. The
+ ``casting`` will be set to ``NPY_EQUIV_CASTING``, ``NPY_SAFE_CASTING``,
+ ``NPY_UNSAFE_CASTING``, or ``NPY_SAME_KIND_CASTING``.
+ A new, additional flag, ``NPY_CAST_IS_VIEW``, can be set to indicate that
+ no cast is necessary and a view is sufficient to perform the cast.
+ The return value shall be ``-1`` to indicate that the cast is not possible.
+ If no error is set, a generic error message will be given. If an error is
+ already set it will be chained and may provide additional information.
+ Note that ``self`` represents additional call information; details are given
+ in NEP 43.
+
+* ``strided_loop(char **args, npy_intp *dimensions, npy_intp *strides,
+ ...) -> int {0, -1}`` (signature will be fully defined in NEP 43)
+
+This is identical to the proposed API for ufuncs. The additional ``...``
+part of the signature will include information such as the two ``dtype``\s.
+More optimized loops are in use internally, and
+will be made available to users in the future (see notes).
+
+Although verbose, the API shall mimic the one for creating a new DType:
+
+.. code-block:: C
typedef struct{
- int needs_api; /* whether the cast requires the API */
- PyArray_DTypeMeta *in_dtype; /* input DType class */
- PyArray_DTypeMeta *out_dtype; /* output DType class */
+ int flags; /* e.g. whether the cast requires the API */
+ int nin, nout; /* Number of Input and outputs (always 1) */
+ NPY_CASTING casting; /* The default casting level */
+ PyArray_DTypeMeta *dtypes; /* input and output DType class */
/* NULL terminated slots defining the methods */
PyType_Slot *slots;
- } PyArrayUFuncImpl_Spec;
-
-The actual creation function ``PyArrayCastingImpl_FromSpec()`` will additionally
-require a ``casting`` parameter to define the default (maximum) casting safety.
-The internal representation of ufuncs and casting implementations may differ
-initially if it makes implementation simpler, but should be kept opaque to
-allow future merging.
+ } PyArrayMethod_Spec;
-**TODO:** It may be possible to make this more close to the ufuncs or even
-use a single FromSpec. This API shall only be finalized after/when NEP 43
-is finalized.
+The focus differs between casting and general ufuncs. For example for casts
+``nin == nout == 1`` is always correct, while for ufuncs ``casting`` is
+expected to be usually `"safe"`.
-**Notes:**
-
-We may initially allow users to define only a single loop.
-However, internally NumPy optimizes far more, and this should be made
-public incrementally, by either allowing to provide multiple versions, such
-as:
+**Notes:** We may initially allow users to define only a single loop. However,
+internally NumPy optimizes far more, and this should be made public
+incrementally, either by allowing multiple versions, such as:
* contiguous inner loop
* strided inner loop
* scalar inner loop
-or more likely through an additional ``get_inner_loop`` function which has
-additional information, such as the fixed strides (similar to our internal API).
+or more likely through exposure of the ``get_loop`` function which is passed
+additional information, such as the fixed strides (similar to our internal
+API).
-The above example does not yet include the definition of setup/teardown
-functionality, which may overlap with ``get_inner_loop``.
-Since these are similar to the UFunc machinery, this should be defined in
-detail in NEP 43 and then incorporated identically into casting.
+The above example does not yet include potential setup and error handling
+requirements. Since these are similar to the UFunc machinery, this will be
+defined in detail in NEP 43 and then incorporated identically into casting.
-Also the ``needs_api`` decision may actually be moved into a setup function,
-and removed or mainly provided as a convenience flag.
+The slots/methods used will be prefixed ``NPY_uf_`` for similarity to the
+ufunc machinery.
-The slots/methods used will be prefixed ``NPY_uf_`` for similarity to the ufunc
-machinery.
+**Alternatives:** Aside from name changes, and possible signature tweaks,
+there seem to be few alternatives to the above structure.
+The proposed API using ``*_FromSpec`` function is a good way to achieve a stable
+and extensible API. The slots design is extensible and can be
+changed without breaking binary compatibility.
+Convenience functions can still be provided to allow creation with less code.
-Alternatives
-""""""""""""
-
-Aside from name changes, and possible signature tweaks, there seem to
-be few alternatives to the above structure.
-Keeping the creation process close the Python limited API has some advantage.
-Convenience functions could still be provided to allow creation with less
-code.
-The central point in the above design is that the enumerated slots design
-is extensible and can be changed without breaking binary compatibility.
-A downside is the possible need to pass in e.g. integer flags using a void
-pointer inside this structure.
-
-A downside of this is that compilers cannot warn about function
-pointer incompatibilities. There is currently no proposed solution to this.
-
-
-Issues
-^^^^^^
-
-Any possible design decision will have issues.
-
-The above split into Python objects has the disadvantage that reference cycles
-naturally occur. For example a potential ``CastingImpl`` object needs to
-hold on to both ``DTypes``. Further, a scalar type may want to own a
-strong reference to the corresponding ``DType`` while the ``DType`` *must*
-hold a strong reference to the scalar.
-We do not believe that these reference cycles are an issue. The may
-require implementation of of cyclic reference counting at some point, but
-cyclic reference resolution is very common in Python and dtypes (especially
-classes) are only a small number of objects.
-
-In some cases, the new split will add additional indirections to the code,
-since methods on the DType have to be looked up and called.
-This should not have serious performance impact and seems necessary to
-achieve the desired flexibility.
-
-From a user-perspective, a more serious downside is that handling certain
-functionality in the ``DType`` rather than directly can mean that error
-messages need to be raised from places where less context is available.
-This may mean that error messages can be less specific.
-This will be alleviated by exception chaining. Also decisions such as
-returning the casting safety (even when it is impossible to cast) allow
-most exceptions to be set at a point where more context is available
-and ensures uniform errors messages.
+One downside of this approach is that compilers cannot warn about function pointer
+incompatibilities.
+******************************************************************************
Implementation
---------------
+******************************************************************************
-Internally a few implementation details have to be decided. These will be
-fully opaque to the user and can be changed at a later time.
+Steps for implementation are outlined in :ref:`NEP 41 <NEP41>`. This includes
+internal restructuring for the new casting and array-coercion.
+First, the NumPy will internally be rewritten using the above methods for
+casting and array-coercion.
-This includes:
+After that, the new public API will be added incrementally.
+We plan to expose it in a preliminary state initially to allow modification
+after some experience can be gained.
+In addition to the features presented in detail in this NEP, all functionality
+currently implemented on the dtypes will be replaced systematically.
-* How ``CastingImpl`` lookup, and thus the decision whether a cast is possible,
- is defined. (This is speed relevant, although mainly during a transition
- phase where UFuncs where NEP 43 is not yet implemented).
- Thus, it is not very relevant to the NEP. It is only necessary to ensure fast
- lookup during the transition phase for the current builtin Numerical types.
-* How the mapping from a python scalar (e.g. ``3.``) to the DType is
- implemented.
-
-The main steps for implementation are outlined in :ref:`NEP 41 <NEP41>`.
-This includes the internal restructure for how casting and array-coercion
-works.
-After this the new public API will be added incrementally.
-This includes replacements for certain slots which are occasionally
-directly used on the dtype (e.g. ``dtype->f->setitem``).
-
-
-Discussion
-----------
+******************************************************************************
+Alternatives
+******************************************************************************
-There is a large space of possible implementations with many discussions
-in various places, as well as initial thoughts and design documents.
-These are listed in the discussion of NEP 40 and not repeated here for
-brevity.
+The space of possible implementations is large, so there have been many
+discussions, conceptions, and design documents. These are listed in NEP 40.
+Since this NEP encompasses multiple individual decisions, alternatives
+are discussed in the above individual sections.
+******************************************************************************
References
-----------
+******************************************************************************
.. [1] NumPy currently inspects the value to allow the operations::
@@ -1335,10 +1366,11 @@ References
np.array([1.2], dtype=np.float32) + 1.
to return a ``uint8`` or ``float32`` array respectively. This is
- further described in the documentation of `numpy.result_type`.
+ further described in the documentation for :func:`numpy.result_type`.
+******************************************************************************
Copyright
----------
+******************************************************************************
This document has been placed in the public domain.