diff options
| -rw-r--r-- | doc/neps/_static/casting_flow.svg | 2212 | ||||
| -rw-r--r-- | doc/neps/_static/dtype_hierarchy.svg | 935 | ||||
| -rw-r--r-- | doc/neps/nep-0042-new-dtypes.rst | 1330 | ||||
| -rw-r--r-- | doc/source/dev/howto-docs.rst | 265 | ||||
| -rw-r--r-- | doc/source/user/building.rst | 12 | ||||
| -rw-r--r-- | numpy/__init__.py | 9 | ||||
| -rw-r--r-- | numpy/core/_add_newdocs.py | 15 | ||||
| -rw-r--r-- | numpy/core/src/umath/simd.inc.src | 8 | ||||
| -rw-r--r-- | numpy/core/tests/test_umath.py | 10 | ||||
| -rw-r--r-- | numpy/ma/extras.py | 11 | ||||
| -rw-r--r-- | site.cfg.example | 8 |
11 files changed, 4649 insertions, 166 deletions
diff --git a/doc/neps/_static/casting_flow.svg b/doc/neps/_static/casting_flow.svg new file mode 100644 index 000000000..8b4b96477 --- /dev/null +++ b/doc/neps/_static/casting_flow.svg @@ -0,0 +1,2212 @@ +<?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:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="908pt" + height="444pt" + viewBox="0 0 908 444" + version="1.1" + id="svg2577" + sodipodi:docname="casting_flow.svg" + inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"> + <metadata + id="metadata2581"> + <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> + <sodipodi:namedview + inkscape:document-rotation="0" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2560" + inkscape:window-height="1376" + id="namedview2579" + showgrid="false" + inkscape:zoom="1.1348363" + inkscape:cx="754.6365" + inkscape:cy="382.73477" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="surface392452" /> + <defs + id="defs1910"> + <g + id="g1908"> + <symbol + overflow="visible" + id="glyph0-0"> + <path + style="stroke:none;" + d="M 0.640625 2.265625 L 0.640625 -9.015625 L 7.03125 -9.015625 L 7.03125 2.265625 Z M 1.359375 1.546875 L 6.328125 1.546875 L 6.328125 -8.296875 L 1.359375 -8.296875 Z M 1.359375 1.546875 " + id="path1734" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-1"> + <path + style="stroke:none;" + d="M 8.234375 -8.609375 L 8.234375 -7.28125 C 7.816406 -7.675781 7.363281 -7.96875 6.875 -8.15625 C 6.394531 -8.351562 5.882812 -8.453125 5.34375 -8.453125 C 4.28125 -8.453125 3.460938 -8.125 2.890625 -7.46875 C 2.328125 -6.820312 2.046875 -5.882812 2.046875 -4.65625 C 2.046875 -3.425781 2.328125 -2.484375 2.890625 -1.828125 C 3.460938 -1.179688 4.28125 -0.859375 5.34375 -0.859375 C 5.882812 -0.859375 6.394531 -0.953125 6.875 -1.140625 C 7.363281 -1.335938 7.816406 -1.632812 8.234375 -2.03125 L 8.234375 -0.71875 C 7.796875 -0.414062 7.328125 -0.1875 6.828125 -0.03125 C 6.335938 0.113281 5.820312 0.1875 5.28125 0.1875 C 3.863281 0.1875 2.75 -0.242188 1.9375 -1.109375 C 1.125 -1.972656 0.71875 -3.15625 0.71875 -4.65625 C 0.71875 -6.15625 1.125 -7.335938 1.9375 -8.203125 C 2.75 -9.066406 3.863281 -9.5 5.28125 -9.5 C 5.832031 -9.5 6.351562 -9.421875 6.84375 -9.265625 C 7.34375 -9.117188 7.804688 -8.898438 8.234375 -8.609375 Z M 8.234375 -8.609375 " + id="path1737" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-2"> + <path + style="stroke:none;" + d="M 4.390625 -3.515625 C 3.460938 -3.515625 2.816406 -3.40625 2.453125 -3.1875 C 2.097656 -2.976562 1.921875 -2.617188 1.921875 -2.109375 C 1.921875 -1.703125 2.050781 -1.378906 2.3125 -1.140625 C 2.582031 -0.898438 2.953125 -0.78125 3.421875 -0.78125 C 4.054688 -0.78125 4.566406 -1.003906 4.953125 -1.453125 C 5.335938 -1.910156 5.53125 -2.515625 5.53125 -3.265625 L 5.53125 -3.515625 Z M 6.671875 -4 L 6.671875 0 L 5.53125 0 L 5.53125 -1.0625 C 5.269531 -0.632812 4.941406 -0.316406 4.546875 -0.109375 C 4.160156 0.0859375 3.679688 0.1875 3.109375 0.1875 C 2.390625 0.1875 1.816406 -0.015625 1.390625 -0.421875 C 0.972656 -0.828125 0.765625 -1.363281 0.765625 -2.03125 C 0.765625 -2.820312 1.023438 -3.414062 1.546875 -3.8125 C 2.078125 -4.21875 2.867188 -4.421875 3.921875 -4.421875 L 5.53125 -4.421875 L 5.53125 -4.53125 C 5.53125 -5.0625 5.351562 -5.46875 5 -5.75 C 4.65625 -6.039062 4.171875 -6.1875 3.546875 -6.1875 C 3.140625 -6.1875 2.75 -6.140625 2.375 -6.046875 C 2 -5.953125 1.632812 -5.8125 1.28125 -5.625 L 1.28125 -6.671875 C 1.695312 -6.835938 2.101562 -6.960938 2.5 -7.046875 C 2.894531 -7.128906 3.28125 -7.171875 3.65625 -7.171875 C 4.675781 -7.171875 5.429688 -6.90625 5.921875 -6.375 C 6.421875 -5.851562 6.671875 -5.0625 6.671875 -4 Z M 6.671875 -4 " + id="path1740" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-3"> + <path + style="stroke:none;" + d="M 5.671875 -6.796875 L 5.671875 -5.703125 C 5.347656 -5.867188 5.007812 -5.992188 4.65625 -6.078125 C 4.300781 -6.160156 3.9375 -6.203125 3.5625 -6.203125 C 3 -6.203125 2.570312 -6.113281 2.28125 -5.9375 C 2 -5.769531 1.859375 -5.507812 1.859375 -5.15625 C 1.859375 -4.882812 1.957031 -4.671875 2.15625 -4.515625 C 2.363281 -4.367188 2.773438 -4.226562 3.390625 -4.09375 L 3.78125 -4 C 4.601562 -3.832031 5.1875 -3.585938 5.53125 -3.265625 C 5.875 -2.941406 6.046875 -2.5 6.046875 -1.9375 C 6.046875 -1.28125 5.785156 -0.757812 5.265625 -0.375 C 4.753906 0 4.050781 0.1875 3.15625 0.1875 C 2.78125 0.1875 2.390625 0.148438 1.984375 0.078125 C 1.578125 0.00390625 1.144531 -0.101562 0.6875 -0.25 L 0.6875 -1.4375 C 1.113281 -1.21875 1.53125 -1.050781 1.9375 -0.9375 C 2.351562 -0.832031 2.765625 -0.78125 3.171875 -0.78125 C 3.710938 -0.78125 4.128906 -0.875 4.421875 -1.0625 C 4.710938 -1.25 4.859375 -1.507812 4.859375 -1.84375 C 4.859375 -2.15625 4.753906 -2.394531 4.546875 -2.5625 C 4.335938 -2.726562 3.875 -2.890625 3.15625 -3.046875 L 2.765625 -3.140625 C 2.046875 -3.285156 1.53125 -3.515625 1.21875 -3.828125 C 0.90625 -4.140625 0.75 -4.566406 0.75 -5.109375 C 0.75 -5.765625 0.976562 -6.269531 1.4375 -6.625 C 1.90625 -6.988281 2.570312 -7.171875 3.4375 -7.171875 C 3.851562 -7.171875 4.25 -7.140625 4.625 -7.078125 C 5 -7.015625 5.347656 -6.921875 5.671875 -6.796875 Z M 5.671875 -6.796875 " + id="path1743" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-4"> + <path + style="stroke:none;" + d="M 2.34375 -8.984375 L 2.34375 -7 L 4.71875 -7 L 4.71875 -6.109375 L 2.34375 -6.109375 L 2.34375 -2.3125 C 2.34375 -1.738281 2.421875 -1.367188 2.578125 -1.203125 C 2.734375 -1.046875 3.050781 -0.96875 3.53125 -0.96875 L 4.71875 -0.96875 L 4.71875 0 L 3.53125 0 C 2.644531 0 2.03125 -0.164062 1.6875 -0.5 C 1.351562 -0.832031 1.1875 -1.4375 1.1875 -2.3125 L 1.1875 -6.109375 L 0.34375 -6.109375 L 0.34375 -7 L 1.1875 -7 L 1.1875 -8.984375 Z M 2.34375 -8.984375 " + id="path1746" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-5"> + <path + style="stroke:none;" + d="M 1.203125 -7 L 2.359375 -7 L 2.359375 0 L 1.203125 0 Z M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 -8.265625 L 1.203125 -8.265625 Z M 1.203125 -9.71875 " + id="path1749" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-6"> + <path + style="stroke:none;" + d="M 7.015625 -4.21875 L 7.015625 0 L 5.875 0 L 5.875 -4.1875 C 5.875 -4.851562 5.742188 -5.347656 5.484375 -5.671875 C 5.222656 -6.003906 4.835938 -6.171875 4.328125 -6.171875 C 3.703125 -6.171875 3.207031 -5.972656 2.84375 -5.578125 C 2.488281 -5.179688 2.3125 -4.640625 2.3125 -3.953125 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.59375 -6.332031 2.914062 -6.648438 3.28125 -6.859375 C 3.65625 -7.066406 4.085938 -7.171875 4.578125 -7.171875 C 5.378906 -7.171875 5.984375 -6.921875 6.390625 -6.421875 C 6.804688 -5.921875 7.015625 -5.1875 7.015625 -4.21875 Z M 7.015625 -4.21875 " + id="path1752" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-7"> + <path + style="stroke:none;" + d="M 5.8125 -3.578125 C 5.8125 -4.410156 5.640625 -5.054688 5.296875 -5.515625 C 4.953125 -5.972656 4.46875 -6.203125 3.84375 -6.203125 C 3.226562 -6.203125 2.75 -5.972656 2.40625 -5.515625 C 2.0625 -5.054688 1.890625 -4.410156 1.890625 -3.578125 C 1.890625 -2.753906 2.0625 -2.113281 2.40625 -1.65625 C 2.75 -1.195312 3.226562 -0.96875 3.84375 -0.96875 C 4.46875 -0.96875 4.953125 -1.195312 5.296875 -1.65625 C 5.640625 -2.113281 5.8125 -2.753906 5.8125 -3.578125 Z M 6.953125 -0.875 C 6.953125 0.320312 6.6875 1.207031 6.15625 1.78125 C 5.632812 2.363281 4.828125 2.65625 3.734375 2.65625 C 3.328125 2.65625 2.945312 2.625 2.59375 2.5625 C 2.238281 2.507812 1.890625 2.421875 1.546875 2.296875 L 1.546875 1.171875 C 1.890625 1.359375 2.222656 1.492188 2.546875 1.578125 C 2.878906 1.671875 3.21875 1.71875 3.5625 1.71875 C 4.3125 1.71875 4.875 1.519531 5.25 1.125 C 5.625 0.726562 5.8125 0.132812 5.8125 -0.65625 L 5.8125 -1.234375 C 5.570312 -0.816406 5.265625 -0.503906 4.890625 -0.296875 C 4.523438 -0.0976562 4.082031 0 3.5625 0 C 2.707031 0 2.015625 -0.328125 1.484375 -0.984375 C 0.960938 -1.640625 0.703125 -2.503906 0.703125 -3.578125 C 0.703125 -4.660156 0.960938 -5.53125 1.484375 -6.1875 C 2.015625 -6.84375 2.707031 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.648438 5.570312 -6.34375 5.8125 -5.9375 L 5.8125 -7 L 6.953125 -7 Z M 6.953125 -0.875 " + id="path1755" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-8"> + <path + style="stroke:none;" + d="M 1.25 -9.328125 L 2.515625 -9.328125 L 2.515625 0 L 1.25 0 Z M 1.25 -9.328125 " + id="path1758" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-9"> + <path + style="stroke:none;" + d="M 6.65625 -5.65625 C 6.9375 -6.164062 7.273438 -6.546875 7.671875 -6.796875 C 8.078125 -7.046875 8.550781 -7.171875 9.09375 -7.171875 C 9.820312 -7.171875 10.382812 -6.914062 10.78125 -6.40625 C 11.175781 -5.894531 11.375 -5.164062 11.375 -4.21875 L 11.375 0 L 10.21875 0 L 10.21875 -4.1875 C 10.21875 -4.851562 10.097656 -5.347656 9.859375 -5.671875 C 9.628906 -6.003906 9.269531 -6.171875 8.78125 -6.171875 C 8.1875 -6.171875 7.710938 -5.972656 7.359375 -5.578125 C 7.015625 -5.179688 6.84375 -4.640625 6.84375 -3.953125 L 6.84375 0 L 5.6875 0 L 5.6875 -4.1875 C 5.6875 -4.863281 5.566406 -5.363281 5.328125 -5.6875 C 5.097656 -6.007812 4.734375 -6.171875 4.234375 -6.171875 C 3.648438 -6.171875 3.179688 -5.96875 2.828125 -5.5625 C 2.484375 -5.164062 2.3125 -4.628906 2.3125 -3.953125 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.582031 -6.332031 2.898438 -6.648438 3.265625 -6.859375 C 3.628906 -7.066406 4.0625 -7.171875 4.5625 -7.171875 C 5.070312 -7.171875 5.503906 -7.039062 5.859375 -6.78125 C 6.222656 -6.519531 6.488281 -6.144531 6.65625 -5.65625 Z M 6.65625 -5.65625 " + id="path1761" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-10"> + <path + style="stroke:none;" + d="M 2.3125 -1.046875 L 2.3125 2.65625 L 1.15625 2.65625 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.9375 C 2.5625 -6.351562 2.867188 -6.660156 3.234375 -6.859375 C 3.597656 -7.066406 4.039062 -7.171875 4.5625 -7.171875 C 5.40625 -7.171875 6.09375 -6.832031 6.625 -6.15625 C 7.15625 -5.476562 7.421875 -4.59375 7.421875 -3.5 C 7.421875 -2.394531 7.15625 -1.503906 6.625 -0.828125 C 6.09375 -0.148438 5.40625 0.1875 4.5625 0.1875 C 4.039062 0.1875 3.597656 0.0859375 3.234375 -0.109375 C 2.867188 -0.316406 2.5625 -0.628906 2.3125 -1.046875 Z M 6.234375 -3.5 C 6.234375 -4.34375 6.054688 -5.003906 5.703125 -5.484375 C 5.359375 -5.960938 4.882812 -6.203125 4.28125 -6.203125 C 3.664062 -6.203125 3.179688 -5.960938 2.828125 -5.484375 C 2.484375 -5.003906 2.3125 -4.34375 2.3125 -3.5 C 2.3125 -2.644531 2.484375 -1.976562 2.828125 -1.5 C 3.179688 -1.019531 3.664062 -0.78125 4.28125 -0.78125 C 4.882812 -0.78125 5.359375 -1.019531 5.703125 -1.5 C 6.054688 -1.976562 6.234375 -2.644531 6.234375 -3.5 Z M 6.234375 -3.5 " + id="path1764" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-11"> + <path + style="stroke:none;" + d="M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 0 L 1.203125 0 Z M 1.203125 -9.71875 " + id="path1767" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-12"> + <path + style="stroke:none;" + d="M 1.09375 -9.71875 L 3.75 -9.71875 L 3.75 -8.828125 L 2.25 -8.828125 L 2.25 0.796875 L 3.75 0.796875 L 3.75 1.6875 L 1.09375 1.6875 Z M 1.09375 -9.71875 " + id="path1770" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-13"> + <path + style="stroke:none;" + d="M 2.453125 -1.0625 L 6.859375 -1.0625 L 6.859375 0 L 0.9375 0 L 0.9375 -1.0625 C 1.414062 -1.5625 2.066406 -2.226562 2.890625 -3.0625 C 3.722656 -3.894531 4.242188 -4.429688 4.453125 -4.671875 C 4.859375 -5.128906 5.140625 -5.515625 5.296875 -5.828125 C 5.460938 -6.140625 5.546875 -6.445312 5.546875 -6.75 C 5.546875 -7.25 5.367188 -7.65625 5.015625 -7.96875 C 4.671875 -8.28125 4.21875 -8.4375 3.65625 -8.4375 C 3.257812 -8.4375 2.84375 -8.363281 2.40625 -8.21875 C 1.96875 -8.082031 1.5 -7.878906 1 -7.609375 L 1 -8.875 C 1.507812 -9.082031 1.984375 -9.238281 2.421875 -9.34375 C 2.867188 -9.445312 3.273438 -9.5 3.640625 -9.5 C 4.609375 -9.5 5.378906 -9.253906 5.953125 -8.765625 C 6.523438 -8.285156 6.8125 -7.640625 6.8125 -6.828125 C 6.8125 -6.453125 6.738281 -6.09375 6.59375 -5.75 C 6.445312 -5.40625 6.1875 -5 5.8125 -4.53125 C 5.707031 -4.40625 5.375 -4.054688 4.8125 -3.484375 C 4.257812 -2.910156 3.472656 -2.101562 2.453125 -1.0625 Z M 2.453125 -1.0625 " + id="path1773" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-14"> + <path + style="stroke:none;" + d="M 4.84375 -8.234375 L 1.65625 -3.25 L 4.84375 -3.25 Z M 4.5 -9.328125 L 6.09375 -9.328125 L 6.09375 -3.25 L 7.421875 -3.25 L 7.421875 -2.203125 L 6.09375 -2.203125 L 6.09375 0 L 4.84375 0 L 4.84375 -2.203125 L 0.625 -2.203125 L 0.625 -3.421875 Z M 4.5 -9.328125 " + id="path1776" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-15"> + <path + style="stroke:none;" + d="M 1.5 -1.59375 L 2.8125 -1.59375 L 2.8125 -0.515625 L 1.796875 1.484375 L 0.984375 1.484375 L 1.5 -0.515625 Z M 1.5 -1.59375 " + id="path1779" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-16"> + <path + style="stroke:none;" + d="" + id="path1782" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-17"> + <path + style="stroke:none;" + d="M 6.84375 -9.015625 L 6.84375 -7.796875 C 6.363281 -8.023438 5.910156 -8.191406 5.484375 -8.296875 C 5.066406 -8.410156 4.660156 -8.46875 4.265625 -8.46875 C 3.578125 -8.46875 3.046875 -8.332031 2.671875 -8.0625 C 2.296875 -7.800781 2.109375 -7.425781 2.109375 -6.9375 C 2.109375 -6.519531 2.234375 -6.207031 2.484375 -6 C 2.734375 -5.789062 3.203125 -5.625 3.890625 -5.5 L 4.65625 -5.34375 C 5.59375 -5.15625 6.285156 -4.835938 6.734375 -4.390625 C 7.179688 -3.941406 7.40625 -3.335938 7.40625 -2.578125 C 7.40625 -1.671875 7.101562 -0.984375 6.5 -0.515625 C 5.894531 -0.046875 5.007812 0.1875 3.84375 0.1875 C 3.394531 0.1875 2.921875 0.132812 2.421875 0.03125 C 1.929688 -0.0703125 1.414062 -0.21875 0.875 -0.40625 L 0.875 -1.71875 C 1.394531 -1.425781 1.898438 -1.207031 2.390625 -1.0625 C 2.878906 -0.914062 3.363281 -0.84375 3.84375 -0.84375 C 4.5625 -0.84375 5.113281 -0.984375 5.5 -1.265625 C 5.894531 -1.546875 6.09375 -1.953125 6.09375 -2.484375 C 6.09375 -2.941406 5.953125 -3.296875 5.671875 -3.546875 C 5.390625 -3.804688 4.925781 -4.003906 4.28125 -4.140625 L 3.515625 -4.28125 C 2.578125 -4.46875 1.894531 -4.757812 1.46875 -5.15625 C 1.050781 -5.5625 0.84375 -6.117188 0.84375 -6.828125 C 0.84375 -7.660156 1.132812 -8.3125 1.71875 -8.78125 C 2.300781 -9.257812 3.101562 -9.5 4.125 -9.5 C 4.5625 -9.5 5.003906 -9.457031 5.453125 -9.375 C 5.910156 -9.300781 6.375 -9.179688 6.84375 -9.015625 Z M 6.84375 -9.015625 " + id="path1785" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-18"> + <path + style="stroke:none;" + d="M 5.265625 -5.921875 C 5.128906 -5.992188 4.984375 -6.046875 4.828125 -6.078125 C 4.679688 -6.117188 4.519531 -6.140625 4.34375 -6.140625 C 3.6875 -6.140625 3.179688 -5.925781 2.828125 -5.5 C 2.484375 -5.082031 2.3125 -4.476562 2.3125 -3.6875 L 2.3125 0 L 1.15625 0 L 1.15625 -7 L 2.3125 -7 L 2.3125 -5.90625 C 2.5625 -6.332031 2.878906 -6.648438 3.265625 -6.859375 C 3.648438 -7.066406 4.117188 -7.171875 4.671875 -7.171875 C 4.753906 -7.171875 4.84375 -7.164062 4.9375 -7.15625 C 5.03125 -7.144531 5.132812 -7.128906 5.25 -7.109375 Z M 5.265625 -5.921875 " + id="path1788" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-19"> + <path + style="stroke:none;" + d="M 3.890625 -9.71875 L 3.890625 1.6875 L 1.25 1.6875 L 1.25 0.796875 L 2.734375 0.796875 L 2.734375 -8.828125 L 1.25 -8.828125 L 1.25 -9.71875 Z M 3.890625 -9.71875 " + id="path1791" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-20"> + <path + style="stroke:none;" + d="M 4.0625 -8.5 C 3.414062 -8.5 2.925781 -8.175781 2.59375 -7.53125 C 2.269531 -6.894531 2.109375 -5.9375 2.109375 -4.65625 C 2.109375 -3.375 2.269531 -2.410156 2.59375 -1.765625 C 2.925781 -1.128906 3.414062 -0.8125 4.0625 -0.8125 C 4.71875 -0.8125 5.207031 -1.128906 5.53125 -1.765625 C 5.863281 -2.410156 6.03125 -3.375 6.03125 -4.65625 C 6.03125 -5.9375 5.863281 -6.894531 5.53125 -7.53125 C 5.207031 -8.175781 4.71875 -8.5 4.0625 -8.5 Z M 4.0625 -9.5 C 5.113281 -9.5 5.914062 -9.082031 6.46875 -8.25 C 7.019531 -7.425781 7.296875 -6.226562 7.296875 -4.65625 C 7.296875 -3.082031 7.019531 -1.878906 6.46875 -1.046875 C 5.914062 -0.222656 5.113281 0.1875 4.0625 0.1875 C 3.019531 0.1875 2.222656 -0.222656 1.671875 -1.046875 C 1.117188 -1.878906 0.84375 -3.082031 0.84375 -4.65625 C 0.84375 -6.226562 1.117188 -7.425781 1.671875 -8.25 C 2.222656 -9.082031 3.019531 -9.5 4.0625 -9.5 Z M 4.0625 -9.5 " + id="path1794" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-21"> + <path + style="stroke:none;" + d="M 5.8125 -5.9375 L 5.8125 -9.71875 L 6.953125 -9.71875 L 6.953125 0 L 5.8125 0 L 5.8125 -1.046875 C 5.570312 -0.628906 5.265625 -0.316406 4.890625 -0.109375 C 4.523438 0.0859375 4.082031 0.1875 3.5625 0.1875 C 2.71875 0.1875 2.03125 -0.148438 1.5 -0.828125 C 0.96875 -1.503906 0.703125 -2.394531 0.703125 -3.5 C 0.703125 -4.59375 0.96875 -5.476562 1.5 -6.15625 C 2.03125 -6.832031 2.71875 -7.171875 3.5625 -7.171875 C 4.082031 -7.171875 4.523438 -7.066406 4.890625 -6.859375 C 5.265625 -6.660156 5.570312 -6.351562 5.8125 -5.9375 Z M 1.890625 -3.5 C 1.890625 -2.644531 2.0625 -1.976562 2.40625 -1.5 C 2.757812 -1.019531 3.238281 -0.78125 3.84375 -0.78125 C 4.457031 -0.78125 4.9375 -1.019531 5.28125 -1.5 C 5.632812 -1.976562 5.8125 -2.644531 5.8125 -3.5 C 5.8125 -4.34375 5.632812 -5.003906 5.28125 -5.484375 C 4.9375 -5.960938 4.457031 -6.203125 3.84375 -6.203125 C 3.238281 -6.203125 2.757812 -5.960938 2.40625 -5.484375 C 2.0625 -5.003906 1.890625 -4.34375 1.890625 -3.5 Z M 1.890625 -3.5 " + id="path1797" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-22"> + <path + style="stroke:none;" + d="M 1.203125 -7 L 2.359375 -7 L 2.359375 0.125 C 2.359375 1.019531 2.1875 1.664062 1.84375 2.0625 C 1.507812 2.457031 0.960938 2.65625 0.203125 2.65625 L -0.234375 2.65625 L -0.234375 1.6875 L 0.078125 1.6875 C 0.515625 1.6875 0.8125 1.582031 0.96875 1.375 C 1.125 1.175781 1.203125 0.757812 1.203125 0.125 Z M 1.203125 -9.71875 L 2.359375 -9.71875 L 2.359375 -8.265625 L 1.203125 -8.265625 Z M 1.203125 -9.71875 " + id="path1800" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-23"> + <path + style="stroke:none;" + d="M 1.09375 -2.765625 L 1.09375 -7 L 2.234375 -7 L 2.234375 -2.8125 C 2.234375 -2.144531 2.363281 -1.644531 2.625 -1.3125 C 2.882812 -0.976562 3.269531 -0.8125 3.78125 -0.8125 C 4.40625 -0.8125 4.894531 -1.007812 5.25 -1.40625 C 5.613281 -1.800781 5.796875 -2.34375 5.796875 -3.03125 L 5.796875 -7 L 6.953125 -7 L 6.953125 0 L 5.796875 0 L 5.796875 -1.078125 C 5.515625 -0.648438 5.191406 -0.332031 4.828125 -0.125 C 4.460938 0.0820312 4.035156 0.1875 3.546875 0.1875 C 2.742188 0.1875 2.132812 -0.0625 1.71875 -0.5625 C 1.300781 -1.0625 1.09375 -1.796875 1.09375 -2.765625 Z M 3.984375 -7.171875 Z M 3.984375 -7.171875 " + id="path1803" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-24"> + <path + style="stroke:none;" + d="M 6.515625 2.125 L 6.515625 3.015625 L -0.125 3.015625 L -0.125 2.125 Z M 6.515625 2.125 " + id="path1806" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-25"> + <path + style="stroke:none;" + d="M 7.1875 -3.78125 L 7.1875 -3.21875 L 1.90625 -3.21875 C 1.957031 -2.425781 2.195312 -1.820312 2.625 -1.40625 C 3.050781 -1 3.644531 -0.796875 4.40625 -0.796875 C 4.84375 -0.796875 5.269531 -0.847656 5.6875 -0.953125 C 6.101562 -1.066406 6.515625 -1.226562 6.921875 -1.4375 L 6.921875 -0.359375 C 6.515625 -0.179688 6.09375 -0.046875 5.65625 0.046875 C 5.21875 0.140625 4.78125 0.1875 4.34375 0.1875 C 3.21875 0.1875 2.328125 -0.132812 1.671875 -0.78125 C 1.023438 -1.4375 0.703125 -2.320312 0.703125 -3.4375 C 0.703125 -4.582031 1.007812 -5.488281 1.625 -6.15625 C 2.25 -6.832031 3.085938 -7.171875 4.140625 -7.171875 C 5.078125 -7.171875 5.816406 -6.863281 6.359375 -6.25 C 6.910156 -5.644531 7.1875 -4.820312 7.1875 -3.78125 Z M 6.046875 -4.125 C 6.035156 -4.75 5.859375 -5.25 5.515625 -5.625 C 5.171875 -6 4.71875 -6.1875 4.15625 -6.1875 C 3.507812 -6.1875 2.992188 -6.003906 2.609375 -5.640625 C 2.222656 -5.285156 2 -4.78125 1.9375 -4.125 Z M 6.046875 -4.125 " + id="path1809" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-26"> + <path + style="stroke:none;" + d="M 6.25 -6.734375 L 6.25 -5.65625 C 5.914062 -5.832031 5.585938 -5.960938 5.265625 -6.046875 C 4.941406 -6.140625 4.613281 -6.1875 4.28125 -6.1875 C 3.53125 -6.1875 2.945312 -5.953125 2.53125 -5.484375 C 2.125 -5.015625 1.921875 -4.351562 1.921875 -3.5 C 1.921875 -2.644531 2.125 -1.976562 2.53125 -1.5 C 2.945312 -1.03125 3.53125 -0.796875 4.28125 -0.796875 C 4.613281 -0.796875 4.941406 -0.835938 5.265625 -0.921875 C 5.585938 -1.015625 5.914062 -1.148438 6.25 -1.328125 L 6.25 -0.265625 C 5.925781 -0.117188 5.59375 -0.0078125 5.25 0.0625 C 4.90625 0.144531 4.539062 0.1875 4.15625 0.1875 C 3.09375 0.1875 2.25 -0.144531 1.625 -0.8125 C 1.007812 -1.476562 0.703125 -2.375 0.703125 -3.5 C 0.703125 -4.632812 1.015625 -5.53125 1.640625 -6.1875 C 2.273438 -6.84375 3.132812 -7.171875 4.21875 -7.171875 C 4.570312 -7.171875 4.914062 -7.132812 5.25 -7.0625 C 5.59375 -6.988281 5.925781 -6.878906 6.25 -6.734375 Z M 6.25 -6.734375 " + id="path1812" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-27"> + <path + style="stroke:none;" + d="M 3.921875 -6.1875 C 3.304688 -6.1875 2.816406 -5.945312 2.453125 -5.46875 C 2.097656 -4.988281 1.921875 -4.332031 1.921875 -3.5 C 1.921875 -2.65625 2.097656 -1.992188 2.453125 -1.515625 C 2.804688 -1.035156 3.296875 -0.796875 3.921875 -0.796875 C 4.535156 -0.796875 5.019531 -1.035156 5.375 -1.515625 C 5.726562 -2.003906 5.90625 -2.664062 5.90625 -3.5 C 5.90625 -4.320312 5.726562 -4.972656 5.375 -5.453125 C 5.019531 -5.941406 4.535156 -6.1875 3.921875 -6.1875 Z M 3.921875 -7.171875 C 4.921875 -7.171875 5.703125 -6.84375 6.265625 -6.1875 C 6.835938 -5.539062 7.125 -4.644531 7.125 -3.5 C 7.125 -2.351562 6.835938 -1.453125 6.265625 -0.796875 C 5.703125 -0.140625 4.921875 0.1875 3.921875 0.1875 C 2.910156 0.1875 2.117188 -0.140625 1.546875 -0.796875 C 0.984375 -1.453125 0.703125 -2.351562 0.703125 -3.5 C 0.703125 -4.644531 0.984375 -5.539062 1.546875 -6.1875 C 2.117188 -6.84375 2.910156 -7.171875 3.921875 -7.171875 Z M 3.921875 -7.171875 " + id="path1815" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-28"> + <path + style="stroke:none;" + d="M 3.96875 -9.703125 C 3.40625 -8.742188 2.988281 -7.796875 2.71875 -6.859375 C 2.445312 -5.929688 2.3125 -4.984375 2.3125 -4.015625 C 2.3125 -3.054688 2.445312 -2.101562 2.71875 -1.15625 C 3 -0.21875 3.414062 0.726562 3.96875 1.6875 L 2.96875 1.6875 C 2.34375 0.707031 1.875 -0.253906 1.5625 -1.203125 C 1.25 -2.148438 1.09375 -3.085938 1.09375 -4.015625 C 1.09375 -4.941406 1.25 -5.875 1.5625 -6.8125 C 1.875 -7.757812 2.34375 -8.722656 2.96875 -9.703125 Z M 3.96875 -9.703125 " + id="path1818" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-29"> + <path + style="stroke:none;" + d="M 1.03125 -9.703125 L 2.03125 -9.703125 C 2.65625 -8.722656 3.117188 -7.757812 3.421875 -6.8125 C 3.734375 -5.875 3.890625 -4.941406 3.890625 -4.015625 C 3.890625 -3.085938 3.734375 -2.148438 3.421875 -1.203125 C 3.117188 -0.253906 2.65625 0.707031 2.03125 1.6875 L 1.03125 1.6875 C 1.582031 0.726562 1.992188 -0.21875 2.265625 -1.15625 C 2.535156 -2.101562 2.671875 -3.054688 2.671875 -4.015625 C 2.671875 -4.984375 2.535156 -5.929688 2.265625 -6.859375 C 1.992188 -7.796875 1.582031 -8.742188 1.03125 -9.703125 Z M 1.03125 -9.703125 " + id="path1821" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-30"> + <path + style="stroke:none;" + d="M 4.0625 -4.4375 C 3.46875 -4.4375 3 -4.273438 2.65625 -3.953125 C 2.3125 -3.628906 2.140625 -3.1875 2.140625 -2.625 C 2.140625 -2.0625 2.3125 -1.617188 2.65625 -1.296875 C 3 -0.972656 3.46875 -0.8125 4.0625 -0.8125 C 4.664062 -0.8125 5.140625 -0.972656 5.484375 -1.296875 C 5.828125 -1.617188 6 -2.0625 6 -2.625 C 6 -3.1875 5.828125 -3.628906 5.484375 -3.953125 C 5.140625 -4.273438 4.664062 -4.4375 4.0625 -4.4375 Z M 2.8125 -4.96875 C 2.269531 -5.101562 1.847656 -5.351562 1.546875 -5.71875 C 1.242188 -6.09375 1.09375 -6.546875 1.09375 -7.078125 C 1.09375 -7.828125 1.359375 -8.414062 1.890625 -8.84375 C 2.421875 -9.28125 3.144531 -9.5 4.0625 -9.5 C 5 -9.5 5.726562 -9.28125 6.25 -8.84375 C 6.78125 -8.414062 7.046875 -7.828125 7.046875 -7.078125 C 7.046875 -6.546875 6.894531 -6.09375 6.59375 -5.71875 C 6.289062 -5.351562 5.875 -5.101562 5.34375 -4.96875 C 5.945312 -4.820312 6.414062 -4.539062 6.75 -4.125 C 7.09375 -3.71875 7.265625 -3.21875 7.265625 -2.625 C 7.265625 -1.71875 6.988281 -1.019531 6.4375 -0.53125 C 5.882812 -0.0507812 5.09375 0.1875 4.0625 0.1875 C 3.039062 0.1875 2.253906 -0.0507812 1.703125 -0.53125 C 1.148438 -1.019531 0.875 -1.71875 0.875 -2.625 C 0.875 -3.21875 1.039062 -3.71875 1.375 -4.125 C 1.71875 -4.539062 2.195312 -4.820312 2.8125 -4.96875 Z M 2.34375 -6.953125 C 2.34375 -6.472656 2.492188 -6.097656 2.796875 -5.828125 C 3.097656 -5.554688 3.519531 -5.421875 4.0625 -5.421875 C 4.601562 -5.421875 5.023438 -5.554688 5.328125 -5.828125 C 5.640625 -6.097656 5.796875 -6.472656 5.796875 -6.953125 C 5.796875 -7.441406 5.640625 -7.820312 5.328125 -8.09375 C 5.023438 -8.363281 4.601562 -8.5 4.0625 -8.5 C 3.519531 -8.5 3.097656 -8.363281 2.796875 -8.09375 C 2.492188 -7.820312 2.34375 -7.441406 2.34375 -6.953125 Z M 2.34375 -6.953125 " + id="path1824" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-31"> + <path + style="stroke:none;" + d="M 1.9375 -1.59375 L 3.203125 -1.59375 L 3.203125 0 L 1.9375 0 Z M 1.9375 -9.328125 L 3.203125 -9.328125 L 3.203125 -5.234375 L 3.078125 -3 L 2.0625 -3 L 1.9375 -5.234375 Z M 1.9375 -9.328125 " + id="path1827" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-32"> + <path + style="stroke:none;" + d="M 1.359375 -5.8125 L 9.359375 -5.8125 L 9.359375 -4.765625 L 1.359375 -4.765625 Z M 1.359375 -3.265625 L 9.359375 -3.265625 L 9.359375 -2.203125 L 1.359375 -2.203125 Z M 1.359375 -3.265625 " + id="path1830" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-33"> + <path + style="stroke:none;" + d="M 4.75 -9.71875 L 4.75 -8.765625 L 3.65625 -8.765625 C 3.238281 -8.765625 2.945312 -8.679688 2.78125 -8.515625 C 2.625 -8.347656 2.546875 -8.046875 2.546875 -7.609375 L 2.546875 -7 L 4.4375 -7 L 4.4375 -6.109375 L 2.546875 -6.109375 L 2.546875 0 L 1.390625 0 L 1.390625 -6.109375 L 0.296875 -6.109375 L 0.296875 -7 L 1.390625 -7 L 1.390625 -7.484375 C 1.390625 -8.265625 1.570312 -8.832031 1.9375 -9.1875 C 2.300781 -9.539062 2.875 -9.71875 3.65625 -9.71875 Z M 4.75 -9.71875 " + id="path1833" /> + </symbol> + <symbol + overflow="visible" + id="glyph0-34"> + <path + style="stroke:none;" + d="M 2.296875 -9.328125 L 2.296875 -5.859375 L 1.234375 -5.859375 L 1.234375 -9.328125 Z M 4.65625 -9.328125 L 4.65625 -5.859375 L 3.59375 -5.859375 L 3.59375 -9.328125 Z M 4.65625 -9.328125 " + id="path1836" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-0"> + <path + style="stroke:none;" + d="M 0.984375 3.484375 L 0.984375 -13.921875 L 10.859375 -13.921875 L 10.859375 3.484375 Z M 2.09375 2.390625 L 9.765625 2.390625 L 9.765625 -12.8125 L 2.09375 -12.8125 Z M 2.09375 2.390625 " + id="path1839" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-1"> + <path + style="stroke:none;" + d="M 12.515625 -6.578125 L 12.515625 0 L 9.046875 0 L 9.046875 -5.03125 C 9.046875 -5.96875 9.023438 -6.613281 8.984375 -6.96875 C 8.941406 -7.320312 8.867188 -7.582031 8.765625 -7.75 C 8.628906 -7.96875 8.445312 -8.140625 8.21875 -8.265625 C 7.988281 -8.390625 7.722656 -8.453125 7.421875 -8.453125 C 6.703125 -8.453125 6.132812 -8.175781 5.71875 -7.625 C 5.3125 -7.070312 5.109375 -6.300781 5.109375 -5.3125 L 5.109375 0 L 1.65625 0 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.21875 C 5.628906 -9.851562 6.179688 -10.316406 6.765625 -10.609375 C 7.347656 -10.910156 7.992188 -11.0625 8.703125 -11.0625 C 9.953125 -11.0625 10.898438 -10.675781 11.546875 -9.90625 C 12.191406 -9.144531 12.515625 -8.035156 12.515625 -6.578125 Z M 12.515625 -6.578125 " + id="path1842" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-2"> + <path + style="stroke:none;" + d="M 5.109375 -1.5625 L 5.109375 4.109375 L 1.65625 4.109375 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.21875 C 5.585938 -9.851562 6.113281 -10.316406 6.6875 -10.609375 C 7.269531 -10.910156 7.9375 -11.0625 8.6875 -11.0625 C 10.019531 -11.0625 11.113281 -10.53125 11.96875 -9.46875 C 12.820312 -8.414062 13.25 -7.054688 13.25 -5.390625 C 13.25 -3.722656 12.820312 -2.359375 11.96875 -1.296875 C 11.113281 -0.242188 10.019531 0.28125 8.6875 0.28125 C 7.9375 0.28125 7.269531 0.128906 6.6875 -0.171875 C 6.113281 -0.472656 5.585938 -0.9375 5.109375 -1.5625 Z M 7.40625 -8.546875 C 6.664062 -8.546875 6.097656 -8.273438 5.703125 -7.734375 C 5.304688 -7.191406 5.109375 -6.410156 5.109375 -5.390625 C 5.109375 -4.367188 5.304688 -3.585938 5.703125 -3.046875 C 6.097656 -2.503906 6.664062 -2.234375 7.40625 -2.234375 C 8.144531 -2.234375 8.707031 -2.5 9.09375 -3.03125 C 9.488281 -3.570312 9.6875 -4.359375 9.6875 -5.390625 C 9.6875 -6.421875 9.488281 -7.203125 9.09375 -7.734375 C 8.707031 -8.273438 8.144531 -8.546875 7.40625 -8.546875 Z M 7.40625 -8.546875 " + id="path1845" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-3"> + <path + style="stroke:none;" + d="M 2.015625 -3.734375 L 5.484375 -3.734375 L 5.484375 0 L 2.015625 0 Z M 2.015625 -3.734375 " + id="path1848" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-4"> + <path + style="stroke:none;" + d="M 6.5 -4.859375 C 5.78125 -4.859375 5.238281 -4.734375 4.875 -4.484375 C 4.507812 -4.242188 4.328125 -3.882812 4.328125 -3.40625 C 4.328125 -2.976562 4.472656 -2.640625 4.765625 -2.390625 C 5.054688 -2.140625 5.460938 -2.015625 5.984375 -2.015625 C 6.640625 -2.015625 7.1875 -2.242188 7.625 -2.703125 C 8.070312 -3.171875 8.296875 -3.757812 8.296875 -4.46875 L 8.296875 -4.859375 Z M 11.78125 -6.15625 L 11.78125 0 L 8.296875 0 L 8.296875 -1.59375 C 7.828125 -0.945312 7.300781 -0.472656 6.71875 -0.171875 C 6.144531 0.128906 5.445312 0.28125 4.625 0.28125 C 3.5 0.28125 2.585938 -0.0390625 1.890625 -0.6875 C 1.191406 -1.34375 0.84375 -2.191406 0.84375 -3.234375 C 0.84375 -4.503906 1.28125 -5.4375 2.15625 -6.03125 C 3.03125 -6.625 4.398438 -6.921875 6.265625 -6.921875 L 8.296875 -6.921875 L 8.296875 -7.1875 C 8.296875 -7.726562 8.078125 -8.125 7.640625 -8.375 C 7.210938 -8.632812 6.539062 -8.765625 5.625 -8.765625 C 4.882812 -8.765625 4.195312 -8.691406 3.5625 -8.546875 C 2.925781 -8.398438 2.335938 -8.175781 1.796875 -7.875 L 1.796875 -10.515625 C 2.535156 -10.691406 3.273438 -10.828125 4.015625 -10.921875 C 4.765625 -11.015625 5.515625 -11.0625 6.265625 -11.0625 C 8.210938 -11.0625 9.617188 -10.675781 10.484375 -9.90625 C 11.347656 -9.132812 11.78125 -7.882812 11.78125 -6.15625 Z M 11.78125 -6.15625 " + id="path1851" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-5"> + <path + style="stroke:none;" + d="M 9.6875 -7.859375 C 9.382812 -8.003906 9.082031 -8.109375 8.78125 -8.171875 C 8.476562 -8.242188 8.175781 -8.28125 7.875 -8.28125 C 6.988281 -8.28125 6.304688 -7.992188 5.828125 -7.421875 C 5.347656 -6.847656 5.109375 -6.03125 5.109375 -4.96875 L 5.109375 0 L 1.65625 0 L 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 -9.03125 C 5.554688 -9.738281 6.066406 -10.253906 6.640625 -10.578125 C 7.210938 -10.898438 7.898438 -11.0625 8.703125 -11.0625 C 8.816406 -11.0625 8.941406 -11.054688 9.078125 -11.046875 C 9.210938 -11.035156 9.410156 -11.015625 9.671875 -10.984375 Z M 9.6875 -7.859375 " + id="path1854" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-6"> + <path + style="stroke:none;" + d="M 0.234375 -10.796875 L 3.6875 -10.796875 L 6.59375 -3.46875 L 9.0625 -10.796875 L 12.515625 -10.796875 L 7.96875 1.015625 C 7.519531 2.222656 6.988281 3.066406 6.375 3.546875 C 5.769531 4.023438 4.96875 4.265625 3.96875 4.265625 L 1.984375 4.265625 L 1.984375 2 L 3.0625 2 C 3.644531 2 4.066406 1.90625 4.328125 1.71875 C 4.597656 1.53125 4.804688 1.195312 4.953125 0.71875 L 5.046875 0.421875 Z M 0.234375 -10.796875 " + id="path1857" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-7"> + <path + style="stroke:none;" + d="M 7.4375 2.609375 L 4.578125 2.609375 C 3.597656 1.015625 2.875 -0.492188 2.40625 -1.921875 C 1.9375 -3.347656 1.703125 -4.769531 1.703125 -6.1875 C 1.703125 -7.59375 1.9375 -9.015625 2.40625 -10.453125 C 2.875 -11.898438 3.597656 -13.410156 4.578125 -14.984375 L 7.4375 -14.984375 C 6.613281 -13.460938 5.992188 -11.972656 5.578125 -10.515625 C 5.171875 -9.054688 4.96875 -7.617188 4.96875 -6.203125 C 4.96875 -4.773438 5.171875 -3.332031 5.578125 -1.875 C 5.992188 -0.414062 6.613281 1.078125 7.4375 2.609375 Z M 7.4375 2.609375 " + id="path1860" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-8"> + <path + style="stroke:none;" + d="M 7.265625 -11.34375 L 3.203125 -5.3125 L 7.265625 -5.3125 Z M 6.65625 -14.390625 L 10.78125 -14.390625 L 10.78125 -5.3125 L 12.828125 -5.3125 L 12.828125 -2.625 L 10.78125 -2.625 L 10.78125 0 L 7.265625 0 L 7.265625 -2.625 L 0.890625 -2.625 L 0.890625 -5.8125 Z M 6.65625 -14.390625 " + id="path1863" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-9"> + <path + style="stroke:none;" + d="M 5.6875 -2.734375 L 12.03125 -2.734375 L 12.03125 0 L 1.5625 0 L 1.5625 -2.734375 L 6.8125 -7.375 C 7.28125 -7.789062 7.628906 -8.203125 7.859375 -8.609375 C 8.085938 -9.015625 8.203125 -9.4375 8.203125 -9.875 C 8.203125 -10.550781 7.972656 -11.09375 7.515625 -11.5 C 7.066406 -11.914062 6.460938 -12.125 5.703125 -12.125 C 5.128906 -12.125 4.5 -12 3.8125 -11.75 C 3.125 -11.5 2.382812 -11.128906 1.59375 -10.640625 L 1.59375 -13.8125 C 2.4375 -14.082031 3.265625 -14.289062 4.078125 -14.4375 C 4.890625 -14.582031 5.691406 -14.65625 6.484375 -14.65625 C 8.203125 -14.65625 9.535156 -14.273438 10.484375 -13.515625 C 11.441406 -12.753906 11.921875 -11.695312 11.921875 -10.34375 C 11.921875 -9.5625 11.71875 -8.832031 11.3125 -8.15625 C 10.914062 -7.476562 10.066406 -6.566406 8.765625 -5.421875 Z M 5.6875 -2.734375 " + id="path1866" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-10"> + <path + style="stroke:none;" + d="M 2.015625 -3.734375 L 5.484375 -3.734375 L 5.484375 -0.796875 L 3.109375 2.8125 L 1.046875 2.8125 L 2.015625 -0.796875 Z M 2.015625 -3.734375 " + id="path1869" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-11"> + <path + style="stroke:none;" + d="" + id="path1872" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-12"> + <path + style="stroke:none;" + d="M 9 -9.21875 L 9 -15 L 12.484375 -15 L 12.484375 0 L 9 0 L 9 -1.5625 C 8.53125 -0.925781 8.007812 -0.457031 7.4375 -0.15625 C 6.863281 0.132812 6.203125 0.28125 5.453125 0.28125 C 4.117188 0.28125 3.023438 -0.242188 2.171875 -1.296875 C 1.316406 -2.359375 0.890625 -3.722656 0.890625 -5.390625 C 0.890625 -7.054688 1.316406 -8.414062 2.171875 -9.46875 C 3.023438 -10.53125 4.117188 -11.0625 5.453125 -11.0625 C 6.191406 -11.0625 6.847656 -10.910156 7.421875 -10.609375 C 8.003906 -10.316406 8.53125 -9.851562 9 -9.21875 Z M 6.734375 -2.234375 C 7.472656 -2.234375 8.035156 -2.5 8.421875 -3.03125 C 8.804688 -3.570312 9 -4.359375 9 -5.390625 C 9 -6.421875 8.804688 -7.203125 8.421875 -7.734375 C 8.035156 -8.273438 7.472656 -8.546875 6.734375 -8.546875 C 5.992188 -8.546875 5.429688 -8.273438 5.046875 -7.734375 C 4.660156 -7.203125 4.46875 -6.421875 4.46875 -5.390625 C 4.46875 -4.359375 4.660156 -3.570312 5.046875 -3.03125 C 5.429688 -2.5 5.992188 -2.234375 6.734375 -2.234375 Z M 6.734375 -2.234375 " + id="path1875" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-13"> + <path + style="stroke:none;" + d="M 5.421875 -13.875 L 5.421875 -10.796875 L 8.984375 -10.796875 L 8.984375 -8.328125 L 5.421875 -8.328125 L 5.421875 -3.75 C 5.421875 -3.25 5.519531 -2.910156 5.71875 -2.734375 C 5.925781 -2.554688 6.328125 -2.46875 6.921875 -2.46875 L 8.6875 -2.46875 L 8.6875 0 L 5.734375 0 C 4.367188 0 3.398438 -0.28125 2.828125 -0.84375 C 2.265625 -1.414062 1.984375 -2.382812 1.984375 -3.75 L 1.984375 -8.328125 L 0.265625 -8.328125 L 0.265625 -10.796875 L 1.984375 -10.796875 L 1.984375 -13.875 Z M 5.421875 -13.875 " + id="path1878" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-14"> + <path + style="stroke:none;" + d="M 12.4375 -5.421875 L 12.4375 -4.453125 L 4.375 -4.453125 C 4.457031 -3.640625 4.75 -3.03125 5.25 -2.625 C 5.75 -2.21875 6.445312 -2.015625 7.34375 -2.015625 C 8.070312 -2.015625 8.816406 -2.117188 9.578125 -2.328125 C 10.335938 -2.546875 11.117188 -2.875 11.921875 -3.3125 L 11.921875 -0.65625 C 11.109375 -0.34375 10.289062 -0.109375 9.46875 0.046875 C 8.65625 0.203125 7.84375 0.28125 7.03125 0.28125 C 5.070312 0.28125 3.550781 -0.210938 2.46875 -1.203125 C 1.382812 -2.203125 0.84375 -3.597656 0.84375 -5.390625 C 0.84375 -7.148438 1.375 -8.535156 2.4375 -9.546875 C 3.507812 -10.554688 4.976562 -11.0625 6.84375 -11.0625 C 8.539062 -11.0625 9.894531 -10.550781 10.90625 -9.53125 C 11.925781 -8.507812 12.4375 -7.140625 12.4375 -5.421875 Z M 8.890625 -6.578125 C 8.890625 -7.234375 8.695312 -7.757812 8.3125 -8.15625 C 7.9375 -8.5625 7.4375 -8.765625 6.8125 -8.765625 C 6.144531 -8.765625 5.601562 -8.578125 5.1875 -8.203125 C 4.769531 -7.828125 4.507812 -7.285156 4.40625 -6.578125 Z M 8.890625 -6.578125 " + id="path1881" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-15"> + <path + style="stroke:none;" + d="M 2.09375 -9.515625 L 14.453125 -9.515625 L 14.453125 -7.25 L 2.09375 -7.25 Z M 2.09375 -5.125 L 14.453125 -5.125 L 14.453125 -2.84375 L 2.09375 -2.84375 Z M 2.09375 -5.125 " + id="path1884" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-16"> + <path + style="stroke:none;" + d="M 1.65625 -10.796875 L 5.109375 -10.796875 L 5.109375 0 L 1.65625 0 Z M 1.65625 -15 L 5.109375 -15 L 5.109375 -12.1875 L 1.65625 -12.1875 Z M 1.65625 -15 " + id="path1887" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-17"> + <path + style="stroke:none;" + d="M 1.578125 2.609375 C 2.398438 1.078125 3.015625 -0.414062 3.421875 -1.875 C 3.835938 -3.332031 4.046875 -4.773438 4.046875 -6.203125 C 4.046875 -7.617188 3.835938 -9.054688 3.421875 -10.515625 C 3.015625 -11.972656 2.398438 -13.460938 1.578125 -14.984375 L 4.453125 -14.984375 C 5.421875 -13.410156 6.140625 -11.898438 6.609375 -10.453125 C 7.085938 -9.015625 7.328125 -7.59375 7.328125 -6.1875 C 7.328125 -4.769531 7.09375 -3.347656 6.625 -1.921875 C 6.15625 -0.492188 5.429688 1.015625 4.453125 2.609375 Z M 1.578125 2.609375 " + id="path1890" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-18"> + <path + style="stroke:none;" + d="M 10.09375 -10.46875 L 10.09375 -7.84375 C 9.351562 -8.144531 8.640625 -8.375 7.953125 -8.53125 C 7.265625 -8.6875 6.617188 -8.765625 6.015625 -8.765625 C 5.359375 -8.765625 4.867188 -8.679688 4.546875 -8.515625 C 4.222656 -8.359375 4.0625 -8.109375 4.0625 -7.765625 C 4.0625 -7.484375 4.179688 -7.269531 4.421875 -7.125 C 4.671875 -6.976562 5.109375 -6.867188 5.734375 -6.796875 L 6.328125 -6.71875 C 8.097656 -6.488281 9.285156 -6.113281 9.890625 -5.59375 C 10.503906 -5.082031 10.8125 -4.28125 10.8125 -3.1875 C 10.8125 -2.03125 10.390625 -1.160156 9.546875 -0.578125 C 8.703125 -0.00390625 7.4375 0.28125 5.75 0.28125 C 5.03125 0.28125 4.289062 0.222656 3.53125 0.109375 C 2.769531 -0.00390625 1.988281 -0.171875 1.1875 -0.390625 L 1.1875 -3.015625 C 1.875 -2.679688 2.578125 -2.429688 3.296875 -2.265625 C 4.023438 -2.097656 4.757812 -2.015625 5.5 -2.015625 C 6.175781 -2.015625 6.6875 -2.109375 7.03125 -2.296875 C 7.375 -2.484375 7.546875 -2.757812 7.546875 -3.125 C 7.546875 -3.4375 7.425781 -3.664062 7.1875 -3.8125 C 6.957031 -3.96875 6.488281 -4.085938 5.78125 -4.171875 L 5.171875 -4.25 C 3.640625 -4.4375 2.5625 -4.789062 1.9375 -5.3125 C 1.320312 -5.832031 1.015625 -6.625 1.015625 -7.6875 C 1.015625 -8.832031 1.40625 -9.679688 2.1875 -10.234375 C 2.976562 -10.785156 4.1875 -11.0625 5.8125 -11.0625 C 6.445312 -11.0625 7.113281 -11.007812 7.8125 -10.90625 C 8.507812 -10.8125 9.269531 -10.664062 10.09375 -10.46875 Z M 10.09375 -10.46875 " + id="path1893" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-19"> + <path + style="stroke:none;" + d="M 8.40625 -14.390625 L 8.40625 -9.046875 L 6.125 -9.046875 L 6.125 -14.390625 Z M 4.171875 -14.390625 L 4.171875 -9.046875 L 1.875 -9.046875 L 1.875 -14.390625 Z M 4.171875 -14.390625 " + id="path1896" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-20"> + <path + style="stroke:none;" + d="M 11.828125 -13.9375 L 11.828125 -10.890625 C 11.035156 -11.242188 10.265625 -11.507812 9.515625 -11.6875 C 8.765625 -11.875 8.054688 -11.96875 7.390625 -11.96875 C 6.503906 -11.96875 5.847656 -11.84375 5.421875 -11.59375 C 4.992188 -11.351562 4.78125 -10.976562 4.78125 -10.46875 C 4.78125 -10.082031 4.921875 -9.78125 5.203125 -9.5625 C 5.492188 -9.34375 6.015625 -9.15625 6.765625 -9 L 8.34375 -8.6875 C 9.945312 -8.363281 11.085938 -7.875 11.765625 -7.21875 C 12.441406 -6.5625 12.78125 -5.628906 12.78125 -4.421875 C 12.78125 -2.835938 12.304688 -1.65625 11.359375 -0.875 C 10.421875 -0.101562 8.984375 0.28125 7.046875 0.28125 C 6.140625 0.28125 5.222656 0.191406 4.296875 0.015625 C 3.378906 -0.148438 2.460938 -0.40625 1.546875 -0.75 L 1.546875 -3.890625 C 2.460938 -3.398438 3.347656 -3.03125 4.203125 -2.78125 C 5.066406 -2.53125 5.894531 -2.40625 6.6875 -2.40625 C 7.5 -2.40625 8.117188 -2.539062 8.546875 -2.8125 C 8.984375 -3.082031 9.203125 -3.46875 9.203125 -3.96875 C 9.203125 -4.414062 9.054688 -4.757812 8.765625 -5 C 8.472656 -5.25 7.890625 -5.472656 7.015625 -5.671875 L 5.578125 -5.984375 C 4.128906 -6.296875 3.070312 -6.789062 2.40625 -7.46875 C 1.75 -8.144531 1.421875 -9.050781 1.421875 -10.1875 C 1.421875 -11.625 1.878906 -12.726562 2.796875 -13.5 C 3.722656 -14.269531 5.054688 -14.65625 6.796875 -14.65625 C 7.585938 -14.65625 8.398438 -14.59375 9.234375 -14.46875 C 10.078125 -14.351562 10.941406 -14.175781 11.828125 -13.9375 Z M 11.828125 -13.9375 " + id="path1899" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-21"> + <path + style="stroke:none;" + d="M 9.078125 -7.21875 C 9.078125 -9.007812 8.910156 -10.273438 8.578125 -11.015625 C 8.242188 -11.753906 7.675781 -12.125 6.875 -12.125 C 6.082031 -12.125 5.515625 -11.753906 5.171875 -11.015625 C 4.828125 -10.273438 4.65625 -9.007812 4.65625 -7.21875 C 4.65625 -5.394531 4.828125 -4.109375 5.171875 -3.359375 C 5.515625 -2.617188 6.082031 -2.25 6.875 -2.25 C 7.664062 -2.25 8.226562 -2.617188 8.5625 -3.359375 C 8.90625 -4.109375 9.078125 -5.394531 9.078125 -7.21875 Z M 12.796875 -7.1875 C 12.796875 -4.800781 12.28125 -2.957031 11.25 -1.65625 C 10.226562 -0.363281 8.769531 0.28125 6.875 0.28125 C 4.976562 0.28125 3.515625 -0.363281 2.484375 -1.65625 C 1.453125 -2.957031 0.9375 -4.800781 0.9375 -7.1875 C 0.9375 -9.570312 1.453125 -11.410156 2.484375 -12.703125 C 3.515625 -14.003906 4.976562 -14.65625 6.875 -14.65625 C 8.769531 -14.65625 10.226562 -14.003906 11.25 -12.703125 C 12.28125 -11.410156 12.796875 -9.570312 12.796875 -7.1875 Z M 12.796875 -7.1875 " + id="path1902" /> + </symbol> + <symbol + overflow="visible" + id="glyph1-22"> + <path + style="stroke:none;" + d="M 15.578125 -6.859375 L 15.578125 -5.515625 L 11.796875 -1.71875 L 10.390625 -3.125 L 12.3125 -5.03125 L 1.125 -5.03125 L 1.125 -7.34375 L 12.3125 -7.34375 L 10.390625 -9.265625 L 11.796875 -10.65625 Z M 15.578125 -6.859375 " + id="path1905" /> + </symbol> + </g> + </defs> + <g + id="surface392452"> + <rect + x="0" + y="0" + width="908" + height="444" + style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;" + id="rect1912" /> + <path + style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:0.592157;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.690003 18.712741 L 47.059925 18.712741 L 47.059925 20.612741 L 37.690003 20.612741 Z M 37.690003 18.712741 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1914" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g1968"> + <use + xlink:href="#glyph0-1" + x="273.335938" + y="24.88878" + id="use1916" /> + <use + xlink:href="#glyph0-2" + x="282.224826" + y="24.88878" + id="use1918" /> + <use + xlink:href="#glyph0-3" + x="290.002604" + y="24.88878" + id="use1920" /> + <use + xlink:href="#glyph0-4" + x="296.669271" + y="24.88878" + id="use1922" /> + <use + xlink:href="#glyph0-5" + x="301.669271" + y="24.88878" + id="use1924" /> + <use + xlink:href="#glyph0-6" + x="305.280382" + y="24.88878" + id="use1926" /> + <use + xlink:href="#glyph0-7" + x="313.335938" + y="24.88878" + id="use1928" /> + <use + xlink:href="#glyph0-8" + x="321.391493" + y="24.88878" + id="use1930" /> + <use + xlink:href="#glyph0-9" + x="325.280382" + y="24.88878" + id="use1932" /> + <use + xlink:href="#glyph0-10" + x="337.780382" + y="24.88878" + id="use1934" /> + <use + xlink:href="#glyph0-11" + x="345.835938" + y="24.88878" + id="use1936" /> + <use + xlink:href="#glyph0-12" + x="349.447049" + y="24.88878" + id="use1938" /> + <use + xlink:href="#glyph0-8" + x="354.447049" + y="24.88878" + id="use1940" /> + <use + xlink:href="#glyph0-6" + x="358.335938" + y="24.88878" + id="use1942" /> + <use + xlink:href="#glyph0-4" + x="366.391493" + y="24.88878" + id="use1944" /> + <use + xlink:href="#glyph0-13" + x="371.391493" + y="24.88878" + id="use1946" /> + <use + xlink:href="#glyph0-14" + x="379.447049" + y="24.88878" + id="use1948" /> + <use + xlink:href="#glyph0-15" + x="387.502604" + y="24.88878" + id="use1950" /> + <use + xlink:href="#glyph0-16" + x="391.669271" + y="24.88878" + id="use1952" /> + <use + xlink:href="#glyph0-17" + x="395.835938" + y="24.88878" + id="use1954" /> + <use + xlink:href="#glyph0-4" + x="403.891493" + y="24.88878" + id="use1956" /> + <use + xlink:href="#glyph0-18" + x="408.891493" + y="24.88878" + id="use1958" /> + <use + xlink:href="#glyph0-5" + x="414.169271" + y="24.88878" + id="use1960" /> + <use + xlink:href="#glyph0-6" + x="417.780382" + y="24.88878" + id="use1962" /> + <use + xlink:href="#glyph0-7" + x="425.835938" + y="24.88878" + id="use1964" /> + <use + xlink:href="#glyph0-19" + x="433.891493" + y="24.88878" + id="use1966" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;" + d="M 42.374964 20.662937 L 42.374964 21.218991 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1970" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 42.124964 21.218991 L 42.374964 21.718991 L 42.624964 21.218991 Z M 42.124964 21.218991 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1972" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 32.07594 22.801609 L 36.211292 22.813327 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1974" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 36.586292 22.814499 L 36.085706 23.063132 L 36.211292 22.813327 L 36.087073 22.563132 Z M 36.586292 22.814499 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1976" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 56.489612 22.817429 L 48.53844 22.825046 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1978" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 48.16344 22.825437 L 48.66305 22.574851 L 48.53844 22.825046 L 48.663636 23.074851 Z M 48.16344 22.825437 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1980" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 41.592932 23.830124 L 40.322034 25.453757 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1982" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 40.090979 25.748874 L 40.202307 25.201218 L 40.322034 25.453757 L 40.596057 25.509421 Z M 40.090979 25.748874 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1984" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 43.056604 23.830124 L 44.151331 25.434812 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1986" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 44.362659 25.744577 L 43.874378 25.472507 L 44.151331 25.434812 L 44.287464 25.190671 Z M 44.362659 25.744577 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1988" /> + <path + style="fill-rule:evenodd;fill:rgb(61.176473%,63.921571%,97.647059%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 29.543714 22.614499 L 32.026331 21.881296 L 32.026331 23.714499 L 29.543714 23.714499 Z M 29.543714 22.614499 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path1990" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2002"> + <use + xlink:href="#glyph0-5" + x="107.921875" + y="94.923937" + id="use1992" /> + <use + xlink:href="#glyph0-6" + x="111.532986" + y="94.923937" + id="use1994" /> + <use + xlink:href="#glyph0-4" + x="119.588542" + y="94.923937" + id="use1996" /> + <use + xlink:href="#glyph0-13" + x="124.588542" + y="94.923937" + id="use1998" /> + <use + xlink:href="#glyph0-14" + x="132.644097" + y="94.923937" + id="use2000" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,70.19608%,14.509805%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 56.539612 22.616257 L 58.539612 21.816257 L 58.539612 23.816257 L 56.539612 23.816257 Z M 56.539612 22.616257 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2004" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2012"> + <use + xlink:href="#glyph0-17" + x="647.332031" + y="95.959093" + id="use2006" /> + <use + xlink:href="#glyph0-13" + x="655.387587" + y="95.959093" + id="use2008" /> + <use + xlink:href="#glyph0-20" + x="663.443142" + y="95.959093" + id="use2010" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 36.747425 21.881101 L 48.002503 21.881101 L 48.002503 23.781101 L 36.747425 23.781101 Z M 36.747425 21.881101 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2014" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2076"> + <use + xlink:href="#glyph0-2" + x="260.152344" + y="88.252062" + id="use2016" /> + <use + xlink:href="#glyph0-21" + x="267.930122" + y="88.252062" + id="use2018" /> + <use + xlink:href="#glyph0-22" + x="275.985677" + y="88.252062" + id="use2020" /> + <use + xlink:href="#glyph0-23" + x="279.596788" + y="88.252062" + id="use2022" /> + <use + xlink:href="#glyph0-3" + x="287.652344" + y="88.252062" + id="use2024" /> + <use + xlink:href="#glyph0-4" + x="294.31901" + y="88.252062" + id="use2026" /> + <use + xlink:href="#glyph0-24" + x="299.31901" + y="88.252062" + id="use2028" /> + <use + xlink:href="#glyph0-21" + x="305.707899" + y="88.252062" + id="use2030" /> + <use + xlink:href="#glyph0-25" + x="313.763455" + y="88.252062" + id="use2032" /> + <use + xlink:href="#glyph0-3" + x="321.541233" + y="88.252062" + id="use2034" /> + <use + xlink:href="#glyph0-26" + x="328.207899" + y="88.252062" + id="use2036" /> + <use + xlink:href="#glyph0-18" + x="335.152344" + y="88.252062" + id="use2038" /> + <use + xlink:href="#glyph0-5" + x="340.430122" + y="88.252062" + id="use2040" /> + <use + xlink:href="#glyph0-10" + x="344.041233" + y="88.252062" + id="use2042" /> + <use + xlink:href="#glyph0-4" + x="352.096788" + y="88.252062" + id="use2044" /> + <use + xlink:href="#glyph0-27" + x="357.096788" + y="88.252062" + id="use2046" /> + <use + xlink:href="#glyph0-18" + x="364.874566" + y="88.252062" + id="use2048" /> + <use + xlink:href="#glyph0-3" + x="370.152344" + y="88.252062" + id="use2050" /> + <use + xlink:href="#glyph0-28" + x="376.81901" + y="88.252062" + id="use2052" /> + <use + xlink:href="#glyph0-5" + x="381.81901" + y="88.252062" + id="use2054" /> + <use + xlink:href="#glyph0-6" + x="385.430122" + y="88.252062" + id="use2056" /> + <use + xlink:href="#glyph0-4" + x="393.485677" + y="88.252062" + id="use2058" /> + <use + xlink:href="#glyph0-13" + x="398.485677" + y="88.252062" + id="use2060" /> + <use + xlink:href="#glyph0-14" + x="406.541233" + y="88.252062" + id="use2062" /> + <use + xlink:href="#glyph0-15" + x="414.596788" + y="88.252062" + id="use2064" /> + <use + xlink:href="#glyph0-16" + x="418.763455" + y="88.252062" + id="use2066" /> + <use + xlink:href="#glyph0-17" + x="422.930122" + y="88.252062" + id="use2068" /> + <use + xlink:href="#glyph0-13" + x="430.985677" + y="88.252062" + id="use2070" /> + <use + xlink:href="#glyph0-20" + x="439.041233" + y="88.252062" + id="use2072" /> + <use + xlink:href="#glyph0-29" + x="447.096788" + y="88.252062" + id="use2074" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.777112 25.887156 L 41.350745 25.887156 L 40.622815 27.887156 L 37.049182 27.887156 Z M 37.777112 25.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2078" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2090"> + <use + xlink:href="#glyph0-5" + x="276.222656" + y="169.377062" + id="use2080" /> + <use + xlink:href="#glyph0-6" + x="279.833767" + y="169.377062" + id="use2082" /> + <use + xlink:href="#glyph0-4" + x="287.889323" + y="169.377062" + id="use2084" /> + <use + xlink:href="#glyph0-13" + x="292.889323" + y="169.377062" + id="use2086" /> + <use + xlink:href="#glyph0-14" + x="300.944878" + y="169.377062" + id="use2088" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 44.26344 25.887156 L 46.748792 25.887156 L 46.020862 27.887156 L 43.535511 27.887156 Z M 44.26344 25.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2092" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2098"> + <use + xlink:href="#glyph0-17" + x="403.40625" + y="169.377062" + id="use2094" /> + <use + xlink:href="#glyph0-30" + x="411.461806" + y="169.377062" + id="use2096" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 57.539612 25.68364 L 59.946643 26.887156 L 57.539612 28.090671 L 55.132776 26.887156 Z M 57.539612 25.68364 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2100" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2106"> + <use + xlink:href="#glyph0-31" + x="651.492188" + y="169.377062" + id="use2102" /> + <use + xlink:href="#glyph0-32" + x="656.492188" + y="169.377062" + id="use2104" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 46.416761 26.887156 L 54.596057 26.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2108" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 54.971057 26.887156 L 54.471057 27.137156 L 54.596057 26.887156 L 54.471057 26.637156 Z M 54.971057 26.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2110" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 57.539612 23.866257 L 57.539612 25.146921 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2112" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 57.539612 25.521921 L 57.289612 25.021921 L 57.539612 25.146921 L 57.789612 25.021921 Z M 57.539612 25.521921 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2114" /> + <path + style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:0.592157;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 60.273401 28.318015 L 69.890979 28.318015 L 69.890979 30.218015 L 60.273401 30.218015 Z M 60.273401 28.318015 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2116" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2172"> + <use + xlink:href="#glyph0-1" + x="724.980469" + y="216.994249" + id="use2118" /> + <use + xlink:href="#glyph0-2" + x="733.869358" + y="216.994249" + id="use2120" /> + <use + xlink:href="#glyph0-3" + x="741.647135" + y="216.994249" + id="use2122" /> + <use + xlink:href="#glyph0-4" + x="748.313802" + y="216.994249" + id="use2124" /> + <use + xlink:href="#glyph0-5" + x="753.313802" + y="216.994249" + id="use2126" /> + <use + xlink:href="#glyph0-6" + x="756.924913" + y="216.994249" + id="use2128" /> + <use + xlink:href="#glyph0-7" + x="764.980469" + y="216.994249" + id="use2130" /> + <use + xlink:href="#glyph0-8" + x="773.036024" + y="216.994249" + id="use2132" /> + <use + xlink:href="#glyph0-9" + x="776.924913" + y="216.994249" + id="use2134" /> + <use + xlink:href="#glyph0-10" + x="789.424913" + y="216.994249" + id="use2136" /> + <use + xlink:href="#glyph0-11" + x="797.480469" + y="216.994249" + id="use2138" /> + <use + xlink:href="#glyph0-12" + x="801.09158" + y="216.994249" + id="use2140" /> + <use + xlink:href="#glyph0-17" + x="806.09158" + y="216.994249" + id="use2142" /> + <use + xlink:href="#glyph0-4" + x="814.147135" + y="216.994249" + id="use2144" /> + <use + xlink:href="#glyph0-18" + x="819.147135" + y="216.994249" + id="use2146" /> + <use + xlink:href="#glyph0-5" + x="824.424913" + y="216.994249" + id="use2148" /> + <use + xlink:href="#glyph0-6" + x="828.036024" + y="216.994249" + id="use2150" /> + <use + xlink:href="#glyph0-7" + x="836.09158" + y="216.994249" + id="use2152" /> + <use + xlink:href="#glyph0-15" + x="844.147135" + y="216.994249" + id="use2154" /> + <use + xlink:href="#glyph0-16" + x="848.313802" + y="216.994249" + id="use2156" /> + <use + xlink:href="#glyph0-17" + x="852.480469" + y="216.994249" + id="use2158" /> + <use + xlink:href="#glyph0-4" + x="860.536024" + y="216.994249" + id="use2160" /> + <use + xlink:href="#glyph0-18" + x="865.536024" + y="216.994249" + id="use2162" /> + <use + xlink:href="#glyph0-5" + x="870.813802" + y="216.994249" + id="use2164" /> + <use + xlink:href="#glyph0-6" + x="874.424913" + y="216.994249" + id="use2166" /> + <use + xlink:href="#glyph0-7" + x="882.480469" + y="216.994249" + id="use2168" /> + <use + xlink:href="#glyph0-19" + x="890.536024" + y="216.994249" + id="use2170" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 51.584729 31.317234 L 63.49469 31.317234 L 63.49469 33.217234 L 51.584729 33.217234 Z M 51.584729 31.317234 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2174" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2234"> + <use + xlink:href="#glyph0-7" + x="565.378906" + y="276.978624" + id="use2176" /> + <use + xlink:href="#glyph0-25" + x="573.434462" + y="276.978624" + id="use2178" /> + <use + xlink:href="#glyph0-4" + x="581.21224" + y="276.978624" + id="use2180" /> + <use + xlink:href="#glyph0-24" + x="586.21224" + y="276.978624" + id="use2182" /> + <use + xlink:href="#glyph0-4" + x="592.601128" + y="276.978624" + id="use2184" /> + <use + xlink:href="#glyph0-18" + x="597.601128" + y="276.978624" + id="use2186" /> + <use + xlink:href="#glyph0-2" + x="602.878906" + y="276.978624" + id="use2188" /> + <use + xlink:href="#glyph0-6" + x="610.656684" + y="276.978624" + id="use2190" /> + <use + xlink:href="#glyph0-3" + x="618.71224" + y="276.978624" + id="use2192" /> + <use + xlink:href="#glyph0-33" + x="625.378906" + y="276.978624" + id="use2194" /> + <use + xlink:href="#glyph0-25" + x="629.823351" + y="276.978624" + id="use2196" /> + <use + xlink:href="#glyph0-18" + x="637.601128" + y="276.978624" + id="use2198" /> + <use + xlink:href="#glyph0-33" + x="642.878906" + y="276.978624" + id="use2200" /> + <use + xlink:href="#glyph0-23" + x="647.323351" + y="276.978624" + id="use2202" /> + <use + xlink:href="#glyph0-6" + x="655.378906" + y="276.978624" + id="use2204" /> + <use + xlink:href="#glyph0-26" + x="663.434462" + y="276.978624" + id="use2206" /> + <use + xlink:href="#glyph0-4" + x="670.378906" + y="276.978624" + id="use2208" /> + <use + xlink:href="#glyph0-5" + x="675.378906" + y="276.978624" + id="use2210" /> + <use + xlink:href="#glyph0-27" + x="678.990017" + y="276.978624" + id="use2212" /> + <use + xlink:href="#glyph0-6" + x="686.767795" + y="276.978624" + id="use2214" /> + <use + xlink:href="#glyph0-28" + x="694.823351" + y="276.978624" + id="use2216" /> + <use + xlink:href="#glyph0-17" + x="699.823351" + y="276.978624" + id="use2218" /> + <use + xlink:href="#glyph0-30" + x="707.878906" + y="276.978624" + id="use2220" /> + <use + xlink:href="#glyph0-15" + x="715.934462" + y="276.978624" + id="use2222" /> + <use + xlink:href="#glyph0-16" + x="720.101128" + y="276.978624" + id="use2224" /> + <use + xlink:href="#glyph0-17" + x="724.267795" + y="276.978624" + id="use2226" /> + <use + xlink:href="#glyph0-13" + x="732.323351" + y="276.978624" + id="use2228" /> + <use + xlink:href="#glyph0-20" + x="740.378906" + y="276.978624" + id="use2230" /> + <use + xlink:href="#glyph0-29" + x="748.434462" + y="276.978624" + id="use2232" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;" + d="M 62.568518 30.267624 L 60.621643 31.041648 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2236" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 60.529456 30.809421 L 60.15719 31.226413 L 60.714026 31.27407 Z M 60.529456 30.809421 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2238" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 57.539612 28.140671 L 57.539612 30.780906 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2240" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 57.539612 31.155906 L 57.289612 30.655906 L 57.539612 30.780906 L 57.789612 30.655906 Z M 57.539612 31.155906 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2242" /> + <path + style="fill-rule:evenodd;fill:rgb(41.176471%,77.254903%,47.058824%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 36.420081 31.317234 L 48.330042 31.317234 L 48.330042 33.217234 L 36.420081 33.217234 Z M 36.420081 31.317234 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2244" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2308"> + <use + xlink:href="#glyph0-7" + x="257.789062" + y="276.978624" + id="use2246" /> + <use + xlink:href="#glyph0-25" + x="265.844618" + y="276.978624" + id="use2248" /> + <use + xlink:href="#glyph0-4" + x="273.622396" + y="276.978624" + id="use2250" /> + <use + xlink:href="#glyph0-24" + x="278.622396" + y="276.978624" + id="use2252" /> + <use + xlink:href="#glyph0-4" + x="285.011285" + y="276.978624" + id="use2254" /> + <use + xlink:href="#glyph0-18" + x="290.011285" + y="276.978624" + id="use2256" /> + <use + xlink:href="#glyph0-2" + x="295.289062" + y="276.978624" + id="use2258" /> + <use + xlink:href="#glyph0-6" + x="303.06684" + y="276.978624" + id="use2260" /> + <use + xlink:href="#glyph0-3" + x="311.122396" + y="276.978624" + id="use2262" /> + <use + xlink:href="#glyph0-33" + x="317.789062" + y="276.978624" + id="use2264" /> + <use + xlink:href="#glyph0-25" + x="322.233507" + y="276.978624" + id="use2266" /> + <use + xlink:href="#glyph0-18" + x="330.011285" + y="276.978624" + id="use2268" /> + <use + xlink:href="#glyph0-33" + x="335.289062" + y="276.978624" + id="use2270" /> + <use + xlink:href="#glyph0-23" + x="339.733507" + y="276.978624" + id="use2272" /> + <use + xlink:href="#glyph0-6" + x="347.789062" + y="276.978624" + id="use2274" /> + <use + xlink:href="#glyph0-26" + x="355.844618" + y="276.978624" + id="use2276" /> + <use + xlink:href="#glyph0-4" + x="362.789062" + y="276.978624" + id="use2278" /> + <use + xlink:href="#glyph0-5" + x="367.789062" + y="276.978624" + id="use2280" /> + <use + xlink:href="#glyph0-27" + x="371.400174" + y="276.978624" + id="use2282" /> + <use + xlink:href="#glyph0-6" + x="379.177951" + y="276.978624" + id="use2284" /> + <use + xlink:href="#glyph0-28" + x="387.233507" + y="276.978624" + id="use2286" /> + <use + xlink:href="#glyph0-5" + x="392.233507" + y="276.978624" + id="use2288" /> + <use + xlink:href="#glyph0-6" + x="395.844618" + y="276.978624" + id="use2290" /> + <use + xlink:href="#glyph0-4" + x="403.900174" + y="276.978624" + id="use2292" /> + <use + xlink:href="#glyph0-13" + x="408.900174" + y="276.978624" + id="use2294" /> + <use + xlink:href="#glyph0-14" + x="416.955729" + y="276.978624" + id="use2296" /> + <use + xlink:href="#glyph0-15" + x="425.011285" + y="276.978624" + id="use2298" /> + <use + xlink:href="#glyph0-16" + x="429.177951" + y="276.978624" + id="use2300" /> + <use + xlink:href="#glyph0-17" + x="433.344618" + y="276.978624" + id="use2302" /> + <use + xlink:href="#glyph0-30" + x="441.400174" + y="276.978624" + id="use2304" /> + <use + xlink:href="#glyph0-29" + x="449.455729" + y="276.978624" + id="use2306" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 39.807776 27.917038 L 41.537659 30.848484 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2310" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 41.728284 31.171335 L 41.258948 30.86782 L 41.537659 30.848484 L 41.689417 30.613718 Z M 41.728284 31.171335 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2312" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 44.612464 27.917038 L 43.111682 30.834812 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2314" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 42.940198 31.16821 L 42.946643 30.609226 L 43.111682 30.834812 L 43.391175 30.837937 Z M 42.940198 31.16821 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2316" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;" + d="M 42.374964 23.831491 L 42.374964 30.654929 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2318" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 42.124964 30.654929 L 42.374964 31.154929 L 42.624964 30.654929 Z M 42.124964 30.654929 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2320" /> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 30.784925 25.633054 L 33.293128 26.887156 L 30.784925 28.141257 L 28.276917 26.887156 Z M 30.784925 25.633054 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2322" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2330"> + <use + xlink:href="#glyph0-31" + x="114.308594" + y="169.377062" + id="use2324" /> + <use + xlink:href="#glyph0-32" + x="119.308594" + y="169.377062" + id="use2326" /> + <use + xlink:href="#glyph0-16" + x="130.141927" + y="169.377062" + id="use2328" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 30.784925 23.76489 L 30.784925 25.096335 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2332" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 30.784925 25.471335 L 30.534925 24.971335 L 30.784925 25.096335 L 31.034925 24.971335 Z M 30.784925 25.471335 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2334" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.381214 26.887156 L 33.830042 26.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2336" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 33.455042 26.887156 L 33.955042 26.637156 L 33.830042 26.887156 L 33.955042 27.137156 Z M 33.455042 26.887156 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2338" /> + <path + style="fill-rule:evenodd;fill:rgb(61.176473%,63.921571%,97.647059%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 28.660706 35.381882 L 32.909339 34.542038 L 32.909339 36.642038 L 28.660706 36.642038 Z M 28.660706 35.381882 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2340" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2360"> + <use + xlink:href="#glyph0-5" + x="94.875" + y="351.869249" + id="use2342" /> + <use + xlink:href="#glyph0-6" + x="98.486111" + y="351.869249" + id="use2344" /> + <use + xlink:href="#glyph0-4" + x="106.541667" + y="351.869249" + id="use2346" /> + <use + xlink:href="#glyph0-13" + x="111.541667" + y="351.869249" + id="use2348" /> + <use + xlink:href="#glyph0-14" + x="119.597222" + y="351.869249" + id="use2350" /> + <use + xlink:href="#glyph0-28" + x="127.652778" + y="351.869249" + id="use2352" /> + <use + xlink:href="#glyph0-14" + x="132.652778" + y="351.869249" + id="use2354" /> + <use + xlink:href="#glyph0-13" + x="140.708333" + y="351.869249" + id="use2356" /> + <use + xlink:href="#glyph0-29" + x="148.763889" + y="351.869249" + id="use2358" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.764612 35.581101 C 37.764612 36.05239 37.000354 36.434421 36.057776 36.434421 C 35.115198 36.434421 34.351136 36.05239 34.351136 35.581101 C 34.351136 35.109812 35.115198 34.727781 36.057776 34.727781 C 37.000354 34.727781 37.764612 35.109812 37.764612 35.581101 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2362" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;" + d="M 40.467932 33.267624 L 37.821448 34.655906 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2364" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.705237 34.434616 L 37.378675 34.888132 L 37.937659 34.87739 Z M 37.705237 34.434616 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2366" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 32.959534 35.587546 L 33.814417 35.585788 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2368" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 34.189417 35.585007 L 33.690003 35.835984 L 33.814417 35.585788 L 33.689026 35.335984 Z M 34.189417 35.585007 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2370" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 37.812268 35.570554 L 39.839807 35.558249 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2372" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 40.214807 35.555906 L 39.71637 35.808835 L 39.839807 35.558249 L 39.713245 35.308835 Z M 40.214807 35.555906 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2374" /> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 40.726721 34.542624 L 44.835315 34.542624 L 44.107386 36.542624 L 39.998792 36.542624 Z M 40.726721 34.542624 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2376" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2394"> + <use + xlink:href="#glyph0-17" + x="330.019531" + y="342.48253" + id="use2378" /> + <use + xlink:href="#glyph0-30" + x="338.075087" + y="342.48253" + id="use2380" /> + <use + xlink:href="#glyph0-28" + x="346.130642" + y="342.48253" + id="use2382" /> + <use + xlink:href="#glyph0-34" + x="351.130642" + y="342.48253" + id="use2384" /> + <use + xlink:href="#glyph0-14" + x="356.963976" + y="342.48253" + id="use2386" /> + <use + xlink:href="#glyph0-13" + x="365.019531" + y="342.48253" + id="use2388" /> + <use + xlink:href="#glyph0-34" + x="373.075087" + y="342.48253" + id="use2390" /> + <use + xlink:href="#glyph0-29" + x="378.90842" + y="342.48253" + id="use2392" /> + </g> + <path + style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 50.59469 35.581101 C 50.59469 36.05239 49.830432 36.434421 48.887854 36.434421 C 47.945276 36.434421 47.181214 36.05239 47.181214 35.581101 C 47.181214 35.109812 47.945276 34.727781 48.887854 34.727781 C 49.830432 34.727781 50.59469 35.109812 50.59469 35.581101 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2396" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.2,0.2;stroke-miterlimit:10;" + d="M 54.927893 33.267624 L 50.860901 34.825437 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2398" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 50.771643 34.591843 L 50.394104 35.004148 L 50.950354 35.058835 Z M 50.771643 34.591843 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2400" /> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 44.49762 35.554929 L 46.650745 35.56782 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2402" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 47.025745 35.569968 L 46.524182 35.817038 L 46.650745 35.56782 L 46.527307 35.317038 Z M 47.025745 35.569968 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2404" /> + <path + style="fill-rule:evenodd;fill:rgb(100%,70.19608%,14.509805%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 54.63805 34.542624 L 61.1693 34.542624 L 60.44137 36.542624 L 53.91012 36.542624 Z M 54.63805 34.542624 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2406" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2426"> + <use + xlink:href="#glyph0-17" + x="628.445313" + y="342.48253" + id="use2408" /> + <use + xlink:href="#glyph0-13" + x="636.500868" + y="342.48253" + id="use2410" /> + <use + xlink:href="#glyph0-20" + x="644.556424" + y="342.48253" + id="use2412" /> + <use + xlink:href="#glyph0-28" + x="652.611979" + y="342.48253" + id="use2414" /> + <use + xlink:href="#glyph0-34" + x="657.611979" + y="342.48253" + id="use2416" /> + <use + xlink:href="#glyph0-14" + x="663.445313" + y="342.48253" + id="use2418" /> + <use + xlink:href="#glyph0-13" + x="671.500868" + y="342.48253" + id="use2420" /> + <use + xlink:href="#glyph0-34" + x="679.556424" + y="342.48253" + id="use2422" /> + <use + xlink:href="#glyph0-29" + x="685.389757" + y="342.48253" + id="use2424" /> + </g> + <path + style="fill:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 50.577698 35.573484 L 53.753479 35.559421 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2428" /> + <path + style="fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" + d="M 54.128479 35.557663 L 53.629651 35.810007 L 53.753479 35.559421 L 53.627503 35.310007 Z M 54.128479 35.557663 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2430" /> + <path + style="fill-rule:evenodd;fill:rgb(100%, 100%, 100%);fill-opacity:1;stroke-width:0.20012599;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%, 0%, 0%);stroke-opacity:1;stroke-miterlimit:10;stroke-dasharray:none" + d="M 24.669495 38.169382 L 66.289417 38.169382 L 66.289417 40.751023 L 24.669495 40.751023 Z M 24.669495 38.169382 " + transform="matrix(20,0,0,20,-491.389899,-372.25483)" + id="path2432" /> + <g + style="fill:rgb(0%,0%,0%);fill-opacity:1;" + id="g2574"> + <use + xlink:href="#glyph1-1" + x="13.492188" + y="422.957954" + id="use2434" /> + <use + xlink:href="#glyph1-2" + x="27.658854" + y="422.957954" + id="use2436" /> + <use + xlink:href="#glyph1-3" + x="41.825521" + y="422.957954" + id="use2438" /> + <use + xlink:href="#glyph1-4" + x="49.325521" + y="422.957954" + id="use2440" /> + <use + xlink:href="#glyph1-5" + x="62.658854" + y="422.957954" + id="use2442" /> + <use + xlink:href="#glyph1-5" + x="72.381076" + y="422.957954" + id="use2444" /> + <use + xlink:href="#glyph1-4" + x="82.103299" + y="422.957954" + id="use2446" /> + <use + xlink:href="#glyph1-6" + x="94.881076" + y="422.957954" + id="use2448" /> + <use + xlink:href="#glyph1-7" + x="107.658854" + y="422.957954" + id="use2450" /> + <use + xlink:href="#glyph1-8" + x="116.825521" + y="422.957954" + id="use2452" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-9" + x="130.436632" + y="422.957954" + id="use2454" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-10" + x="144.047743" + y="422.957954" + id="use2456" /> + <use + xlink:href="#glyph1-11" + x="151.547743" + y="422.957954" + id="use2458" /> + <use + xlink:href="#glyph1-12" + x="158.492188" + y="422.957954" + id="use2460" /> + <use + xlink:href="#glyph1-13" + x="172.658854" + y="422.957954" + id="use2462" /> + <use + xlink:href="#glyph1-6" + x="182.103299" + y="422.957954" + id="use2464" /> + <use + xlink:href="#glyph1-2" + x="194.881076" + y="422.957954" + id="use2466" /> + <use + xlink:href="#glyph1-14" + x="209.047743" + y="422.957954" + id="use2468" /> + <use + xlink:href="#glyph1-15" + x="222.381076" + y="422.957954" + id="use2470" /> + <use + xlink:href="#glyph1-16" + x="239.047743" + y="422.957954" + id="use2472" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-1" + x="245.71441" + y="422.957954" + id="use2474" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-13" + x="259.881076" + y="422.957954" + id="use2476" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-9" + x="269.325521" + y="422.957954" + id="use2478" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-8" + x="282.936632" + y="422.957954" + id="use2480" + style="fill:#9ca1f8;fill-opacity:1" /> + <use + xlink:href="#glyph1-17" + x="296.547743" + y="422.957954" + id="use2482" /> + <use + xlink:href="#glyph1-3" + x="305.71441" + y="422.957954" + id="use2484" /> + <use + xlink:href="#glyph1-4" + x="313.21441" + y="422.957954" + id="use2486" /> + <use + xlink:href="#glyph1-18" + x="326.547743" + y="422.957954" + id="use2488" /> + <use + xlink:href="#glyph1-13" + x="338.21441" + y="422.957954" + id="use2490" /> + <use + xlink:href="#glyph1-6" + x="347.658854" + y="422.957954" + id="use2492" /> + <use + xlink:href="#glyph1-2" + x="360.436632" + y="422.957954" + id="use2494" /> + <use + xlink:href="#glyph1-14" + x="374.603299" + y="422.957954" + id="use2496" /> + <use + xlink:href="#glyph1-7" + x="387.936632" + y="422.957954" + id="use2498" /> + <use + xlink:href="#glyph1-19" + x="397.103299" + y="422.957954" + id="use2500" + style="fill:#000000;fill-opacity:1" /> + <use + xlink:href="#glyph1-20" + x="407.381076" + y="422.957954" + id="use2502" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-9" + x="421.547743" + y="422.957954" + id="use2504" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-21" + x="435.158854" + y="422.957954" + id="use2506" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-19" + x="448.769965" + y="422.957954" + id="use2508" + style="fill:#000000;fill-opacity:1" /> + <use + xlink:href="#glyph1-17" + x="459.047743" + y="422.957954" + id="use2510" /> + <use + xlink:href="#glyph1-11" + x="468.21441" + y="422.957954" + id="use2512" /> + <use + xlink:href="#glyph1-11" + x="475.158854" + y="422.957954" + id="use2514" /> + <use + xlink:href="#glyph1-22" + x="482.103299" + y="422.957954" + id="use2516" /> + <use + xlink:href="#glyph1-11" + x="498.769965" + y="422.957954" + id="use2518" /> + <use + xlink:href="#glyph1-1" + x="505.71441" + y="422.957954" + id="use2520" /> + <use + xlink:href="#glyph1-2" + x="519.881076" + y="422.957954" + id="use2522" /> + <use + xlink:href="#glyph1-3" + x="534.047743" + y="422.957954" + id="use2524" /> + <use + xlink:href="#glyph1-4" + x="541.547743" + y="422.957954" + id="use2526" /> + <use + xlink:href="#glyph1-5" + x="554.881076" + y="422.957954" + id="use2528" /> + <use + xlink:href="#glyph1-5" + x="564.603299" + y="422.957954" + id="use2530" /> + <use + xlink:href="#glyph1-4" + x="574.325521" + y="422.957954" + id="use2532" /> + <use + xlink:href="#glyph1-6" + x="587.103299" + y="422.957954" + id="use2534" /> + <use + xlink:href="#glyph1-7" + x="599.881076" + y="422.957954" + id="use2536" /> + <use + xlink:href="#glyph1-19" + x="609.047743" + y="422.957954" + id="use2538" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-8" + x="619.325521" + y="422.957954" + id="use2540" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-9" + x="632.936632" + y="422.957954" + id="use2542" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-19" + x="646.547743" + y="422.957954" + id="use2544" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-10" + x="656.825521" + y="422.957954" + id="use2546" /> + <use + xlink:href="#glyph1-11" + x="664.325521" + y="422.957954" + id="use2548" /> + <use + xlink:href="#glyph1-12" + x="671.269965" + y="422.957954" + id="use2550" /> + <use + xlink:href="#glyph1-13" + x="685.436632" + y="422.957954" + id="use2552" /> + <use + xlink:href="#glyph1-6" + x="694.881076" + y="422.957954" + id="use2554" /> + <use + xlink:href="#glyph1-2" + x="707.658854" + y="422.957954" + id="use2556" /> + <use + xlink:href="#glyph1-14" + x="721.825521" + y="422.957954" + id="use2558" /> + <use + xlink:href="#glyph1-15" + x="735.158854" + y="422.957954" + id="use2560" /> + <use + xlink:href="#glyph1-19" + x="751.825521" + y="422.957954" + id="use2562" /> + <use + xlink:href="#glyph1-20" + x="762.103299" + y="422.957954" + id="use2564" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-9" + x="776.269965" + y="422.957954" + id="use2566" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-21" + x="789.881076" + y="422.957954" + id="use2568" + style="fill:#ffb323;fill-opacity:1" /> + <use + xlink:href="#glyph1-19" + x="803.492188" + y="422.957954" + id="use2570" /> + <use + xlink:href="#glyph1-17" + x="813.769965" + y="422.957954" + id="use2572" /> + </g> + <text + xml:space="preserve" + style="font-size:14.6266px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke:#cccccc;stroke-width:0.483685" + x="61.029861" + y="206.28314" + id="text2605"><tspan + sodipodi:role="line" + id="tspan2603" + x="61.029861" + y="206.28314" + style="stroke:#cccccc;stroke-width:0.483685">cast not required</tspan></text> + <text + id="text2609" + y="127.66325" + x="395.55035" + style="font-size:14.6266px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;stroke:#cccccc;stroke-width:0.483685" + xml:space="preserve"><tspan + style="stroke:#cccccc;stroke-width:0.483685" + y="127.66325" + x="395.55035" + id="tspan2607" + sodipodi:role="line">only implements S8</tspan></text> + </g> +</svg> diff --git a/doc/neps/_static/dtype_hierarchy.svg b/doc/neps/_static/dtype_hierarchy.svg new file mode 100644 index 000000000..3bade3d0f --- /dev/null +++ b/doc/neps/_static/dtype_hierarchy.svg @@ -0,0 +1,935 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<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" + width="432.64694mm" + height="374.31384mm" + viewBox="0 0 432.64693 374.31384" + version="1.1" + id="svg8" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" + sodipodi:docname="dtype_hierarchy.svg" + inkscape:export-filename="/home/sebastian/BIDS/dtypes/dtype_hierarchy.png" + inkscape:export-xdpi="43.502129" + inkscape:export-ydpi="43.502129"> + <defs + id="defs2"> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker1380" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="Arrow2Mend"> + <path + transform="scale(-0.6)" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" + id="path1378" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Mstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path835" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="matrix(0.4,0,0,0.4,4,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow2Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow2Mend" + style="overflow:visible" + inkscape:isstock="true" + inkscape:collect="always"> + <path + id="path856" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(-0.6)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Send" + orient="auto" + refY="0" + refX="0" + id="Arrow1Send" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path844" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="matrix(-0.2,0,0,-0.2,-1.2,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lend" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path832" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="matrix(-0.8,0,0,-0.8,-10,0)" + inkscape:connector-curvature="0" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.49497475" + inkscape:cx="-261.18562" + inkscape:cy="440.75659" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="3440" + inkscape:window-height="1376" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="10" + fit-margin-left="10" + fit-margin-right="10" + fit-margin-bottom="10" /> + <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 + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(1.2604327,40.771063)"> + <rect + style="opacity:1;fill:#ff9000;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2120" + width="44.63401" + height="17.105249" + x="23.573442" + y="161.07759" + rx="2.843874" + ry="2.5766025" /> + <text + id="text2124" + y="172.67239" + x="30.910395" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" + xml:space="preserve"><tspan + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" + y="172.67239" + x="30.910395" + id="tspan2122" + sodipodi:role="line">DType</tspan></text> + <g + id="g1288"> + <rect + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2146" + width="61.739262" + height="17.105249" + x="42.09428" + y="203.41173" + rx="2.843874" + ry="2.5766025" /> + <text + id="text2150" + y="215.00667" + x="56.400177" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="215.00667" + x="56.400177" + id="tspan2148" + sodipodi:role="line">Float64</tspan></text> + </g> + <g + id="g1283"> + <rect + ry="2.5766025" + rx="2.843874" + y="182.24493" + x="42.09428" + height="17.105249" + width="61.739262" + id="rect2154" + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="61.425056" + y="194.36903" + id="text2158"><tspan + sodipodi:role="line" + id="tspan2156" + x="61.425056" + y="194.36903" + style="stroke-width:0.26458332">Int64</tspan></text> + </g> + <g + id="g1334" + transform="translate(46.037524,104.2459)"> + <path + inkscape:connector-curvature="0" + id="path827" + d="m 58.264755,86.658881 h 10.69078" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + sodipodi:nodetypes="cc" /> + </g> + <g + transform="translate(25.819071,143.16003)" + id="g2205"> + <rect + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2199" + width="44.63401" + height="17.105249" + x="92.475258" + y="39.0849" + rx="0" + ry="0" /> + <text + id="text2203" + y="50.67984" + x="99.81221" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="50.67984" + x="99.81221" + id="tspan2201" + sodipodi:role="line">>int64</tspan></text> + </g> + <g + id="g2213" + transform="translate(75.560923,143.16003)"> + <rect + ry="0" + rx="0" + y="39.0849" + x="92.475258" + height="17.105249" + width="44.63401" + id="rect2207" + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="99.81221" + y="50.67984" + id="text2211"><tspan + sodipodi:role="line" + id="tspan2209" + x="99.81221" + y="50.67984" + style="stroke-width:0.26458332"><int64</tspan></text> + </g> + <g + id="g2663" + transform="translate(-50.910137,157.97679)"> + <g + id="g2645" + transform="translate(96.947661,-32.563904)"> + <path + inkscape:connector-curvature="0" + id="path2643" + d="m 58.264755,86.658881 h 10.69078" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + sodipodi:nodetypes="cc" /> + </g> + <g + transform="translate(76.729209,6.3500001)" + id="g2653"> + <rect + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2647" + width="44.63401" + height="17.105249" + x="92.475258" + y="39.0849" + rx="0" + ry="0" /> + <text + id="text2651" + y="50.67984" + x="97.166374" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="50.67984" + x="97.166374" + id="tspan2649" + sodipodi:role="line">>float64</tspan></text> + </g> + <g + id="g2661" + transform="translate(126.47106,6.3500001)"> + <rect + ry="0" + rx="0" + y="39.0849" + x="92.475258" + height="17.105249" + width="44.63401" + id="rect2655" + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="96.637207" + y="50.67984" + id="text2659"><tspan + sodipodi:role="line" + id="tspan2657" + x="96.637207" + y="50.67984" + style="stroke-width:0.26458332"><float64</tspan></text> + </g> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.51278019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="146.93526" + y="178.48193" + id="text2737"><tspan + sodipodi:role="line" + id="tspan2735" + x="146.93526" + y="178.48193" + style="fill:#9866cf;fill-opacity:1;stroke-width:0.26458332">Instances</tspan></text> + <text + id="text2675-3" + y="153.10063" + x="8.1723146" + style="font-style:normal;font-weight:normal;font-size:11.38954353px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329" + xml:space="preserve"><tspan + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329" + y="153.10063" + x="8.1723146" + id="tspan2673-6" + sodipodi:role="line">Concrete Types:</tspan></text> + <text + id="text3215" + y="72.108665" + x="243.3298" + style="font-style:normal;font-weight:normal;font-size:8.51278019px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="fill:#9866cf;fill-opacity:1;stroke-width:0.26458332" + y="72.108665" + x="243.3298" + id="tspan3213" + sodipodi:role="line">Instances</tspan></text> + <g + id="g1293"> + <rect + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2146-6" + width="61.739262" + height="17.105249" + x="42.297195" + y="224.75034" + rx="2.843874" + ry="2.5766025" /> + <text + id="text2150-7" + y="236.34528" + x="47.843731" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="236.34528" + x="47.843731" + id="tspan2148-5" + sodipodi:role="line">datetime64</tspan></text> + </g> + <g + transform="translate(-50.910137,179.14359)" + id="g1057"> + <g + transform="translate(96.947661,-32.563904)" + id="g1039"> + <path + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + d="m 58.264755,86.658881 h 10.69078" + id="path1037" + inkscape:connector-curvature="0" /> + </g> + <g + id="g1047" + transform="translate(76.729209,6.3500001)"> + <rect + ry="0" + rx="0" + y="39.0849" + x="92.475258" + height="17.105249" + width="44.63401" + id="rect1041" + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="98.777588" + y="50.67984" + id="text1045"><tspan + sodipodi:role="line" + id="tspan1043" + x="98.777588" + y="50.67984" + style="stroke-width:0.26458332"><M8[s]</tspan></text> + </g> + <g + transform="translate(126.47106,6.3500001)" + id="g1055"> + <rect + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1049" + width="44.63401" + height="17.105249" + x="92.475258" + y="39.0849" + rx="0" + ry="0" /> + <text + id="text1053" + y="50.67984" + x="96.000237" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="50.67984" + x="96.000237" + id="tspan1051" + sodipodi:role="line">>M8[ns]</tspan></text> + <rect + ry="0" + rx="0" + y="39.0849" + x="92.475258" + height="17.105249" + width="44.63401" + id="rect1207" + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + id="g1265" + style="fill:#9866cf;fill-opacity:1" + transform="matrix(2.2707534,0,0,2.2707534,-177.4572,-60.535544)"> + <circle + r="1.1358955" + cy="47.637524" + cx="141.20377" + id="path1256" + style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <circle + style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="circle1258" + cx="144.21054" + cy="47.637524" + r="1.1358955" /> + <circle + r="1.1358955" + cy="47.637524" + cx="147.21733" + id="circle1260" + style="opacity:1;fill:#9866cf;fill-opacity:1;stroke:none;stroke-width:1.71979165;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.38954353px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329" + x="8.1723146" + y="-22.317886" + id="text2802"><tspan + sodipodi:role="line" + id="tspan2800" + x="8.1723146" + y="-22.317886" + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329">Concept:</tspan></text> + <ellipse + ry="11.626225" + rx="29.800554" + cy="-4.7734947" + cx="53.874973" + id="path2804" + style="opacity:1;fill:#ffc553;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" + x="28.792381" + y="-2.5054595" + id="text2808"><tspan + sodipodi:role="line" + id="tspan2806" + x="28.792381" + y="-2.5054595" + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1">DTypeMeta</tspan></text> + <rect + ry="2.5766025" + rx="2.843874" + y="-14.100398" + x="96.558197" + height="17.105249" + width="44.63401" + id="rect2810" + style="opacity:1;fill:#ff9000;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" + x="104.69695" + y="-3.0399978" + id="text2814"><tspan + sodipodi:role="line" + id="tspan2812" + x="104.69695" + y="-3.0399978" + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1">DType</tspan></text> + <g + transform="translate(25.655198,-91.784983)" + id="g2818"> + <path + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + d="m 58.264755,86.658881 h 10.69078" + id="path2816" + inkscape:connector-curvature="0" /> + </g> + <g + id="g2846" + transform="translate(4.3286934,-30.623148)"> + <rect + ry="2.5766025" + rx="2.843874" + y="39.0849" + x="108.87944" + height="52.384823" + width="90.871613" + id="rect2840" + style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="112.0525" + y="50.851093" + id="text2844"><tspan + id="tspan2842" + sodipodi:role="line" + x="112.0525" + y="50.851093" + style="stroke-width:0.26458332">AbstractDtypes:</tspan><tspan + sodipodi:role="line" + x="112.0525" + y="62.140648" + style="stroke-width:0.26458332" + id="tspan3068">• type hierarchy</tspan><tspan + sodipodi:role="line" + x="112.0525" + y="73.430199" + style="stroke-width:0.26458332" + id="tspan3078">• UFunc resolution</tspan><tspan + sodipodi:role="line" + x="112.0525" + y="84.719757" + style="stroke-width:0.26458332" + id="tspan3072">• may promote</tspan><tspan + sodipodi:role="line" + x="112.0525" + y="96.009308" + style="stroke-width:0.26458332" + id="tspan3066" /></text> + </g> + <g + transform="translate(20.732865,35.976636)" + id="g2854"> + <rect + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2848" + width="91.940727" + height="47.306705" + x="92.475258" + y="39.0849" + rx="2.843874" + ry="2.5766025" /> + <text + id="text2852" + y="49.872658" + x="96.583473" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="49.872658" + x="96.583473" + id="tspan2850" + sodipodi:role="line">Concrete DTypes:</tspan><tspan + style="stroke-width:0.26458332" + y="60.811176" + x="96.583473" + sodipodi:role="line" + id="tspan3086">• casting/promotion</tspan><tspan + style="stroke-width:0.26458332" + y="71.749695" + x="96.583473" + sodipodi:role="line" + id="tspan3088">• UFunc signature</tspan></text> + </g> + <g + transform="translate(148.727,10.030009)" + id="g2858"> + <path + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + d="m 58.264755,86.658881 h 10.69078" + id="path2856" + inkscape:connector-curvature="0" /> + </g> + <rect + style="opacity:1;fill:none;fill-opacity:1;stroke:#9866cf;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2860" + width="84.724449" + height="45.435818" + x="220.98373" + y="75.328812" + rx="0" + ry="0" /> + <text + id="text2864" + y="86.923752" + x="228.32069" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="86.923752" + x="228.32069" + id="tspan2862" + sodipodi:role="line">DType Instances</tspan><tspan + id="tspan3074" + style="stroke-width:0.26458332" + y="97.862267" + x="228.32069" + sodipodi:role="line">• Describe data</tspan><tspan + id="tspan3076" + style="stroke-width:0.26458332" + y="108.80079" + x="228.32069" + sodipodi:role="line">• `arr.dtype`</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="228.32069" + y="38.240372" + id="text3096"><tspan + sodipodi:role="line" + x="228.32069" + y="38.240372" + style="stroke-width:0.26458332" + id="tspan3094">(Cannot be instantiated)</tspan></text> + <text + id="text3223" + y="277.53149" + x="163.20908" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + id="tspan3221" + style="stroke-width:0.26458332" + y="277.53149" + x="163.20908" + sodipodi:role="line">Concrete Types form</tspan><tspan + style="stroke-width:0.26458332" + y="288.47" + x="163.20908" + sodipodi:role="line" + id="tspan3225">leaves of the tree;</tspan><tspan + id="tspan3248" + style="stroke-width:0.26458332" + y="299.40854" + x="163.20908" + sodipodi:role="line">the inheritance is abstract</tspan><tspan + id="tspan3270" + style="stroke-width:0.26458332" + y="310.34705" + x="163.20908" + sodipodi:role="line">similar to Python's abc.ABC. </tspan></text> + <g + id="g3084" + transform="translate(35.454183,8.4666671)"> + <g + transform="translate(111.41246,-60.58556)" + id="g3058"> + <path + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" + d="m 58.264755,86.658881 h 10.69078" + id="path3056" + inkscape:connector-curvature="0" /> + </g> + <text + id="text3062" + y="33.375549" + x="177.81163" + style="font-style:normal;font-weight:normal;font-size:25.73707581px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="33.375549" + x="177.81163" + id="tspan3060" + sodipodi:role="line">x</tspan></text> + </g> + <path + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" + id="path3217" + d="m 240.37519,140.22719 v 115.49978 l -21.73363,-0.0959" + style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cc" + style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 373.75879,132.43914 H 41.810036" + id="path3219" + inkscape:connector-curvature="0" /> + <g + id="g1383" + transform="translate(1.5875)"> + <g + transform="translate(282.50926,124.19261)" + id="g1309"> + <rect + ry="2.5766025" + rx="2.843874" + y="182.24493" + x="42.09428" + height="17.105249" + width="61.739262" + id="rect1303" + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="61.425056" + y="194.36903" + id="text1307"><tspan + sodipodi:role="line" + id="tspan1305" + x="61.425056" + y="194.36903" + style="stroke-width:0.26458332">Int64</tspan></text> + </g> + <g + transform="translate(283.57834,60.501707)" + id="g1301"> + <rect + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1295" + width="61.739262" + height="17.105249" + x="42.09428" + y="203.41173" + rx="2.843874" + ry="2.5766025" /> + <text + id="text1299" + y="215.00667" + x="56.400177" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="215.00667" + x="56.400177" + id="tspan1297" + sodipodi:role="line">Float64</tspan></text> + </g> + <g + transform="translate(185.91751,182.30441)" + id="g2195"> + <rect + style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect2187" + width="44.63401" + height="17.105249" + x="108.87944" + y="39.0849" + rx="2.843874" + ry="2.5766025" /> + <text + id="text2193" + y="50.321926" + x="113.11084" + style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="50.321926" + x="113.11084" + sodipodi:role="line" + id="tspan2191">Inexact</tspan></text> + </g> + <g + id="g2671" + transform="translate(172.15917,161.04236)"> + <rect + ry="2.5766025" + rx="2.843874" + y="39.0849" + x="108.87944" + height="17.105249" + width="44.63401" + id="rect2665" + style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="112.0525" + y="50.851093" + id="text2669"><tspan + id="tspan2667" + sodipodi:role="line" + x="112.0525" + y="50.851093" + style="stroke-width:0.26458332">Numeric</tspan></text> + </g> + <g + id="g2701" + transform="translate(170.57168,118.51826)"> + <rect + ry="2.5766025" + rx="2.843874" + y="39.0849" + x="92.475258" + height="17.105249" + width="44.63401" + id="rect2695" + style="opacity:1;fill:#ff9153;fill-opacity:1;stroke:none;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="99.81221" + y="50.67984" + id="text2699"><tspan + sodipodi:role="line" + id="tspan2697" + x="99.81221" + y="50.67984" + style="stroke-width:0.26458332">DType</tspan></text> + </g> + <g + id="g2709" + transform="translate(201.26335,203.56648)"> + <rect + ry="2.5766025" + rx="2.843874" + y="39.0849" + x="108.87944" + height="17.105249" + width="44.63401" + id="rect2703" + style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="112.0525" + y="50.321926" + id="text2707"><tspan + id="tspan2705" + sodipodi:role="line" + x="112.0525" + y="50.321926" + style="stroke-width:0.26458332">Floating</tspan></text> + </g> + <g + id="g2717" + transform="translate(185.38297,221.7489)"> + <rect + ry="2.5766025" + rx="2.843874" + y="63.42659" + x="108.87944" + height="17.105249" + width="44.63401" + id="rect2711" + style="opacity:1;fill:none;fill-opacity:1;stroke:#ff9153;stroke-width:1.16499996;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:9.03164291px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="113.11084" + y="74.663612" + id="text2715"><tspan + id="tspan2713" + sodipodi:role="line" + x="113.11084" + y="74.663612" + style="stroke-width:0.26458332">Integral</tspan></text> + </g> + <text + id="text2774" + y="149.89339" + x="244.4957" + style="font-style:normal;font-weight:normal;font-size:11.38954258px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329" + xml:space="preserve"><tspan + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.26458329" + y="149.89339" + x="244.4957" + id="tspan2772" + sodipodi:role="line">Abstract Types (Hierarchy):</tspan></text> + <g + transform="translate(238.74141,-45.88513)" + id="g1317"> + <rect + style="opacity:1;fill:#4dabcf;fill-opacity:1;stroke:none;stroke-width:1.37016749;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect1311" + width="61.739262" + height="17.105249" + x="42.297195" + y="224.75034" + rx="2.843874" + ry="2.5766025" /> + <text + id="text1315" + y="236.34528" + x="47.843731" + style="font-style:normal;font-weight:normal;font-size:8.75081348px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + xml:space="preserve"><tspan + style="stroke-width:0.26458332" + y="236.34528" + x="47.843731" + id="tspan1313" + sodipodi:role="line">datetime64</tspan></text> + </g> + </g> + </g> +</svg> diff --git a/doc/neps/nep-0042-new-dtypes.rst b/doc/neps/nep-0042-new-dtypes.rst new file mode 100644 index 000000000..1c44c68ea --- /dev/null +++ b/doc/neps/nep-0042-new-dtypes.rst @@ -0,0 +1,1330 @@ +======================================== +NEP 42 — Implementation of New DataTypes +======================================== + +:title: Extensible Datatypes for NumPy +:Author: Sebastian Berg +:Status: Draft +:Type: Standard +:Created: 2019-07-17 + + +.. 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. + + +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. + + +.. note:: + + 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. + + +Detailed Description +-------------------- + +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. + +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. + +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. + + +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 `dtype hierarchy figure <hierarchy_figure>`_ for an +illustration of this distinction. + +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). + + +Proposed access to DType class +"""""""""""""""""""""""""""""" + +**Motivation:** + +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. + +**Description:** + +To avoid duplication, but also to expose the classes conveniently to users +we propose the addition of:: + + np.dtype[np.int64] + +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. + +This should not be a common operation, so providing this class getter reduces +the pressure of adding the new DType classes into the namespace. + +*Note: This is currently a possible extension and not yet decided.* + + +Hierarchy of DTypes and Abstract DTypes +""""""""""""""""""""""""""""""""""""""" + +**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. + +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. + + +Additional Information +^^^^^^^^^^^^^^^^^^^^^^ + +In addition to the more detailed methods below, the following general +information is currently provided and will be defined on the class: + +* ``cls.parametric`` (see also `NEP 40 <NEP40>`_): + + * 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). + +* ``self.canonical`` method (Alternative: new instance attribute) + + * 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. + +* ``ensure_canonical(self) -> dtype`` return a new dtype (or ``self``). + The returned dtype must have the ``canonical`` flag set. + +* ``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. + +Additionally, existing methods (and C-side fields) will be provided. +However, the fields ``kind`` and 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). + +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: + +* ``dtype_get_sort_function(self, sortkind="stable") -> sortfunction`` + +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. + +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. + +**Alternatives:** + +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. + +**Example:** + +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. + + +**Issues and Details:** + +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 +categoircal'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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Motivation:** + +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. + +**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`` + 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.) + +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. + + +**Implementation:** + +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. + +**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 +Python ``datetime.datetime`` object (most of the time). + + +**Alternatives:** + +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: + +* 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. + +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. + + +**Further Issues and Discussion:** + +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)``. + +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. + +.. note:: + + 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) + +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 ``type`` which is already associated with any dtype through the +``dtype.type`` attribute maps the DType to the Python type. +This will be cached globally to create a mapping (dictionary) +``known_python_types[type] = DType``. +NumPy currently uses a small hard-coded mapping and conversion of numpy scalars +(inheriting from ``np.generic``) to achieve this. + +.. note:: + + 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 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 functionality provided by + ``np.result_type(python_integer, array)``. + +To allow for a DType to accept specific inputs as known scalars, we will +initially use a method such as ``known_scalar_type`` or ``known_scalar_object`` +which allows discovering an e.g. ``vector`` as a scalar (element) instead of +a sequence (for the command ``np.array(vector, dtype=VectorDType)``). +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:: + + 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, 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. + +The full algorithm (without user provided dtype) 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] + + # Same as 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 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.dtype`` or similar. + +Initially, the exact implementation shall be *undefined*, since +scalars will have to derive from a NumPy scalar, they will also have +a ``.dtype`` attribute. A future update can choose to use this instead +of a global mapping. + +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:: + + 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. + +**Example:** + +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:: + + np.array(["2020-01-02", "2020-01-02 11:24"], dtype="M8") + +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". + + +Common DType Operations +^^^^^^^^^^^^^^^^^^^^^^^ + +Numpy currently provides functions like ``np.result_type`` and +``np.promote_types`` for determining common types. +These differ in that ``np.result_type`` can take arrays and scalars as input +and implements value based promotion [1]_. + +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). +This includes an interesting distinction: + +1. Universal functions use the DType classes for dispatching, they thus + require the common DType class (as a first step). + While this can help with finding the correct loop to execute, the loop + may not need the actual common dtype instance. + (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). + +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). +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). + 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: + +1. ``Float64.__common_dtype__(type(>float64), type(S8))`` + returns `String` (or defers to ``String.__common_dtype__``). +2. The casting machinery provides the information that `">float64"` casts + 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]``. + +This means the implementation will work like this:: + + def common_dtype(DType1, DType2): + common_dtype = type(dtype1).__common_dtype__(type(dtype2)) + if common_dtype is NotImplemented: + common_dtype = type(dtype2).__common_dtype__(type(dtype1)) + if common_dtype is NotImplemented: + raise TypeError("no common dtype") + return common_dtype + + def promote_types(dtype1, dtyp2): + common = common_dtype(type(dtype1), type(dtype2)) + + if type(dtype1) is not common: + # 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)) + assert safety == "safe" # promotion should normally be a safe cast + + if type(dtype2) is not common: + # Same as above branch for dtype1. + + if dtype1 is not dtype2: + return common.__common_instance__(dtype1, dtype2) + +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``. + +However, this cannot define all such operations, and will fail for example for:: + + np.promote_types("int64", "float32") -> np.dtype("float64") + +In this design, it is the responsibility of the DType author to ensure that +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". +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. + +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:: + + HighPrecisionDatetime.__common_dtype__(np.dtype[np.datetime64]) + +would return ``HighPrecisionDatetime``, and the below casting may need to +decide how to handle the datetime unit. + + +Casting +^^^^^^^ + +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: + +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. + +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: + +1. The input 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. + +Further, NumPy provides different casting kinds or safety specifiers: + +* "safe" +* "same_kind" +* "unsafe" + +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: + +1. ``arr.astype(np.String)`` (current spelling ``arr.astype("S")``) +2. ``arr.astype(np.dtype("S8"))``. + +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. +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) + +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. + +Each ``CastingImpl`` has a specific DType signature: +``CastingImpl[InputDtype, RequestedDtype]``. +And implements the following methods and attributes: + +* ``adjust_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 + quickly decide casting safety when this is relevant. + +``adjust_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 +with the signature. + +**Performing the Cast:** + +.. _cast_figure: +.. figure:: _static/casting_flow.svg + :figclass: align-center + +`The above figure <cast_figure>`_ illustrates the multi-step logic necessary to +cast for example an ``int24`` with a value of ``42`` to a string of length 20 +(``"S20"``). +In this example, the implementer only provided the functionality of casting +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"))``. + This provides the information that ``CastingImpl[Int24, String]`` only + 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")``. + +Note that in this example the ``adjust_descriptors`` function plays a less +central role. It becomes more important for ``np.can_cast``. + +Further, ``adjust_descriptors`` allows the implementation for +``np.array(42, dtype=int24).astype(String)`` to call +``CastingImpl[Int24, String].adjust_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:** + +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. + +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. + +(For more information on the ``adjust_descriptor`` signature see the +C-API section below.) + + +**Casting between instances of the same DType:** + +In general one of the casting implementations define 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. + + +**General Multi-Step 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 arbitray ``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 +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)``. +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 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 + + from_dtype = from_dtype.ensure_canonical() # ensure not byte-swapped + if to_dtype is None: + raise TypeError("Cannot convert to a NumPy datetime without a unit") + to_dtype = to_dtype.ensure_canonical() # ensure not byte-swapped + + # This is always an "unsafe" cast, but for int64, we can represent + # it by a simple view (if the dtypes are both canonical). + # (represented as C-side flags here). + safety_and_view = NPY_UNSAFE_CASTING | NPY_CAST_IS_VIEW + return safety_and_view, (from_dtype, to_dtype) + +.. 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``. + + +C-Side API +^^^^^^^^^^ + +A Python side API shall not be defined here. This is a general side approach. + + +DType creation +"""""""""""""" + +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:: + + static struct PyArrayMethodDef slots[] = { + {NPY_dt_method, method_implementation}, + ..., + {0, NULL} + } + + 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) */ + /* NULL terminated CastingImpl; is copied and references are stolen */ + CastingImpl *castingimpls[]; + PyType_Slot *slots; + PyTypeObject *baseclass; /* Baseclass or NULL */ + } PyArrayDTypeMeta_Spec; + + PyObject* PyArray_InitDTypeMetaFromSpec(PyArrayDTypeMeta_Spec *dtype_spec); + +all of this information will be copied during instantiation. + +**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. + + +The proposed method slots are (prepended with ``NPY_dt_``), these are +detailed above and given here for summary: + +* ``is_canonical(self) -> {0, 1}`` +* ``ensure_canonical(self) -> dtype`` +* ``default_descr(self) -> dtype`` (return must be native and should normally be a singleton) +* ``setitem(self, char *item_ptr, PyObject *value) -> {-1, 0}`` +* ``getitem(self, char *item_ptr, PyObject (base_obj) -> object or NULL`` +* ``discover_descr_from_pyobject(cls, PyObject) -> dtype or NULL`` +* ``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. +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: + +* ``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: + +* ``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. + +**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. + 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``:: + + 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 */ + /* 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. + +**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. + +**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: + +* 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). + +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. + +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. + + + +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. + + +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. + +This includes: + +* 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 +---------- + +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. + + +References +---------- + +.. [1] NumPy currently inspects the value to allow the operations:: + + np.array([1], dtype=np.uint8) + 1 + 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`. + + +Copyright +--------- + +This document has been placed in the public domain. diff --git a/doc/source/dev/howto-docs.rst b/doc/source/dev/howto-docs.rst index e8bafd254..17194bd58 100644 --- a/doc/source/dev/howto-docs.rst +++ b/doc/source/dev/howto-docs.rst @@ -4,146 +4,153 @@ How to contribute to the NumPy documentation ############################################ -The *Documentation* for a software project is the set of reference, -instructional, educational, informative material generated by the project -developers and contributors, as well as discussions, presentations, videos and -other user-generated content. It may include learning-oriented content (such as -tutorials and how-tos), use-cases or in-depth explanations and reference for -developers. - -If you're reading this page, you probably want to help. This guide is meant to -help you decide which kind of content you'll write, as well as give you some -tips and instructions for submitting it to the official NumPy documentation -(that is, the documentation that ships with NumPy and lives on the -:ref:`official project pages <numpy_docs_mainpage>`). Keep in mind that if you -don't want to do this, writing a tutorial on your own blog, creating a YouTube -video or answering questions on social media or Stack Overflow are also great -contributions! - -NumPy has a Documentation Team. We have open meetings on Zoom every three weeks -and invite everyone to join. Don't hesitate to reach out if you have questions -or just need someone to guide you through your first steps - we're always happy -to help. Meetings are usually announced on the `numpy-discussion mailing list -<https://mail.python.org/mailman/listinfo/numpy-discussion>`__. Meeting minutes -are taken `on hackmd.io <https://hackmd.io/oB_boakvRqKR-_2jRV-Qjg>`__ and stored -in the `NumPy Archive repository <https://github.com/numpy/archive>`__. - -You can find larger planned and in-progress documentation improvement ideas `at +This guide will help you decide what to contribute and how to submit it to the +official NumPy documentation. + +****************************************************************************** +Documentation team meetings +****************************************************************************** + +The NumPy community has set a firm goal of improving its documentation. We +hold regular documentation meetings on Zoom (dates are announced on the +`numpy-discussion mailing list +<https://mail.python.org/mailman/listinfo/numpy-discussion>`__), and everyone +is welcome. Reach out if you have questions or need +someone to guide you through your first steps -- we're happy to help. +Minutes are taken `on hackmd.io <https://hackmd.io/oB_boakvRqKR-_2jRV-Qjg>`__ +and stored in the `NumPy Archive repository +<https://github.com/numpy/archive>`__. + +************************* +What's needed +************************* +NumPy docs have the details covered. API reference +documentation is generated directly from +`docstrings <https://www.python.org/dev/peps/pep-0257/>`_ in the code +when the documentation is :ref:`built<howto-build-docs>`. + +What we lack are docs with broader scope -- tutorials, how-tos, and explanations. +Reporting defects is another way to contribute. We discuss both. + +************************* +Contributing fixes +************************* + +We're eager to hear about and fix doc defects. But to attack the biggest +problems we end up having to defer or overlook some bug reports. Here are the +best defects to go after. + +Top priority goes to **technical inaccuracies** -- a docstring missing a +parameter, a faulty description of a function/parameter/method, and so on. +Other "structural" defects like broken links also get priority. All these fixes +are easy to confirm and put in place. You can submit +a `pull request (PR) <https://numpy.org/devdocs/dev/index.html#devindex>`__ +with the fix, if you know how to do that; otherwise please `open an issue +<https://github.com/numpy/numpy/issues>`__. + +**Typos and misspellings** fall on a lower rung; we welcome hearing about them but +may not be able to fix them promptly. These too can be handled as pull +requests or issues. + +Obvious **wording** mistakes (like leaving out a "not") fall into the typo +category, but other rewordings -- even for grammar -- require a judgment call, +which raises the bar. Test the waters by first presenting the fix as an issue. + +****************************************************************************** +Contributing new pages +****************************************************************************** + +Your frustrations using our documents are our best guide to what needs fixing. + +If you write a missing doc you join the front line of open source, but it's +a meaningful contribution just to let us know what's missing. If you want to +compose a doc, run your thoughts by the `mailing list +<https://mail.python.org/mailman/listinfo/numpy-discussion>`__ for futher +ideas and feedback. If you want to alert us to a gap, +`open an issue <https://github.com/numpy/numpy/issues>`__. See +`this issue <https://github.com/numpy/numpy/issues/15760>`__ for an example. + +If you're looking for subjects, our formal roadmap for documentation is a +*NumPy Enhancement Proposal (NEP)*, +`NEP 44 - Restructuring the NumPy Documentation <https://www.numpy.org/neps/nep-0044-restructuring-numpy-docs>`__. +It identifies areas where our docs need help and lists several +additions we'd like to see, including Jupyter notebooks. + +You can find larger planned and in-progress ideas `at our GitHub project <https://github.com/orgs/numpy/projects/2>`__. -Current vision for the documentation: NEP 44 --------------------------------------------- +.. _tutorials_howtos_explanations: -Recently, the NumPy community approved a *NumPy Enhancement Proposal (NEP)* -about documentation, -:ref:`NEP 44 - Restructuring the NumPy Documentation <NEP44>`. -**Where is the documentation?** +Formula writing +============================================================================== +There are formulas for writing useful documents, and four formulas +cover nearly everything. There are four formulas because there are four +categories of document -- ``tutorial``, ``how-to guide``, ``explanation``, +and ``reference``. The insight that docs divide up this way belongs to +Daniele Procida, who goes on +`in this short article <https://documentation.divio.com/>`__ to explain +the differences and reveal the formulas. When you begin a document or +propose one, have in mind which of these types it will be. -The main page for the :ref:`NumPy Documentation <numpy_docs_mainpage>` lists -several categories. The documents mentioned there live in different places. -- **Tutorials, How-Tos, Explanations:** These documents are stored in the NumPy - source code tree, which means that in order to add them to the official - documentation, you have to download the NumPy source code, - :ref:`build it <howto-build-docs>` and submit your changes via a - :ref:`GitHub pull request <devindex>`. +.. _contributing: -- **API Reference:** These are mainly the result of rendering the NumPy code - `docstrings <https://www.python.org/dev/peps/pep-0257/>`__ into formatted - documents. They are automatically generated when the NumPy documentation is - :ref:`built from source<howto-build-docs>`. -**Datasets** +More on contributing +============================================================================== -If you are writing a tutorial or how-to, we encourage you to use real images and -data (provided they are appropriately licensed and available). This makes the -material more engaging for readers, and choosing the right data can add -pedagogical value to your content. +Don't worry if English is not your first language, or if you can only come up +with a rough draft. Open source is a community effort. Do your best -- we'll +help fix issues. -*Note: currently we cannot easily use data in other packages (except, e.g., from -SciPy or Matplotlib). We plan to create a dedicated datasets package, but that's -not ready yet - please discuss with us if you have data sources in mind.* +Images and real-life data make text more engaging and powerful, but be sure +what you use is appropriately licensed and available. Here again, even a rough +idea for artwork can be polished by others. -Creating new content --------------------- +For now, the only data formats accepted by NumPy are those also used by other +Python scientific libraries like pandas, SciPy, or Matplotlib. We're +developing a package to accept more formats; contact us for details. -The documentation is written in restructuredText, which is the format required -by Sphinx, the tool most Python projects use to automatically build and link the -documentation within the project. You can read the -`Quick reStructuredText Guide +NumPy documentation is kept in the source code tree. To get your document +into the docbase you must download the tree, :ref:`build it +<howto-build-docs>`, and submit a pull request. If GitHub and pull requests +are new to you, check our :ref:`Contributor Guide <devindex>`. + +Our markup language is reStructuredText (rST), which is more elaborate than +Markdown. Sphinx, the tool many Python projects use to build and link project +documentation, converts the rST into HTML and other formats. For more on +rST, see the `Quick reStructuredText Guide <https://docutils.sourceforge.io/docs/user/rst/quickref.html>`__ or the `reStructuredText Primer -<http://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html>`__ for -more information. - -If you have already decided which type of document you want to write, you can -check out the following specific guides: - -- Guide to writing Tutorials (TODO) -- :ref:`Guide to writing reference (API) documentation: the numpydoc docstring - guide <howto-document>` - -Major additions to the documentation (e.g. new tutorials) should be proposed to -the `mailing list -<https://mail.python.org/mailman/listinfo/numpy-discussion>`__. - -Other ways to contribute ------------------------- - -Correcting technical inaccuracies in the documentation are high priority. For -example, if a docstring is missing a parameter or the description of a -fuction/parameter/method etc. is incorrect. Other "structural" defects like -broken links are also high priority. - -Proposals for changes that improve the clarity of the documentation are welcome. -However, "clarity" is a bit subjective, so such proposals are best made by -raising issues that describe what could be improved in the current -documentation. Proposals that include specific suggestions for the improvement -are encouraged as the proposed changes helps frame the discussion. - -Based on the above characterization, "high-priority" changes (i.e. fixing -technical inaccuracies, broken links, etc.) can be proposed via pull requests -directly as they are straightforward to review. Other changes should be raised -as issues first so that the discussion can happen before you make major -modifications, which in principle saves you from wasting your time on -undesired changes. - -If you see a good tutorial, how-to or explanation that is not included in the -official documentation, you can suggest it to be added by `opening an issue on -GitHub <https://github.com/numpy/numpy/issues>`__. Similarly, opening issues to -suggest a tutorial, how-to or explanation that you can't find anywhere is a -great way to help the documentation team direct efforts towards what users are -looking for. `See this issue <https://github.com/numpy/numpy/issues/15760>`__ -for an example of how to do this. - -Finally, if you detect a typo or an error in the documentation, or would like to -suggest a different approach, you can also open an issue or submit a pull -request with your suggestion. Keep in mind that changes fixing -grammatical/spelling errors are welcome but not necessarily the highest -priority. "Grammatical correctness" often gets confused with "style" which can -result in unfruitful discussions that don't necessarily improve anything. -Changes that modify wording or rearrange phrasing without changing the technical -content are discouraged. If you think that a different wording improves clarity, -you should open an issue as noted above, but again, changes along these lines -very often tend to be highly subjective and not necessarily do much to improve -the quality of the documentation. - -**Final tips** - -- Don't worry if English is not your first language. Do your best - we'll revise - your content and make sure we fix any issues with the code or text. -- If you are unsure whether your tutorial is useful to the community, consider - submitting an issue on GitHub suggesting it, or asking on the mailing - list or Stack Overflow. -- If you are unfamiliar with git/GitHub or the process of submitting a pull - request (PR), check our :ref:`Contributor Guide <devindex>`. - -**Other interesting material** - -- `writethedocs.org <https://www.writethedocs.org/>`__ has a lot of interesting - resources for technical writing. -- Google offers two free `Technical Writing Courses - <https://developers.google.com/tech-writing>`__ -- `Software Carpentry <https://carpentries.github.io/curriculum-development/>`__ has a lot of - nice recommendations for creating educational material. +<http://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html>`__ + + +************************************************************ +Contributing indirectly +************************************************************ + +If you run across outside material that would be a useful addition to the +NumPy docs, let us know by `opening an issue <https://github.com/numpy/numpy/issues>`__. + +You don't have to contribute here to contribute to NumPy. You've contributed +if you write a tutorial on your blog, create a YouTube video, or answer questions +on Stack Overflow and other sites. + + +************************************************************ +Documentation reading +************************************************************ + +- The leading organization of technical writers, + `Write the Docs <https://www.writethedocs.org/>`__, + holds conferences, hosts learning resources, and runs a Slack channel. + +- "Every engineer is also a writer," says Google's + `collection of technical writing resources <https://developers.google.com/tech-writing>`__, + which includes free online courses for developers in planning and writing + documents. + +- `Software Carpentry's <https://software-carpentry.org/lessons>`__ mission is + teaching software to researchers. In addition to hosting the curriculum, the + website explains how to present ideas effectively. diff --git a/doc/source/user/building.rst b/doc/source/user/building.rst index 47a0a03c9..6a880b59e 100644 --- a/doc/source/user/building.rst +++ b/doc/source/user/building.rst @@ -6,6 +6,10 @@ Building from source A general overview of building NumPy from source is given here, with detailed instructions for specific platforms given separately. +.. + This page is referenced from numpy/numpy/__init__.py. Please keep its + location in sync with the link there. + Prerequisites ------------- @@ -159,6 +163,14 @@ will prefer to use ATLAS, then OpenBLAS and as a last resort MKL. If neither of these exists the build will fail (names are compared lower case). +.. deprecated:: 1.20 + The native libraries on macOS, provided by Accelerate, are not fit for use + in NumPy since they have bugs that cause wrong output under easily reproducible + conditions. If the vendor fixes those bugs, the library could be reinstated, + but until then users compiling for themselves should use another linear + algebra library or use the built-in (but slower) default, see the next + section. + Disabling ATLAS and other accelerated libraries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/numpy/__init__.py b/numpy/__init__.py index e6a24f0d1..1c3b11844 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -279,12 +279,11 @@ else: error_message = "{}: {}".format(w[-1].category.__name__, str(w[-1].message)) msg = ( "Polyfit sanity test emitted a warning, most likely due " - "to using a buggy Accelerate backend. " - "If you compiled yourself, " - "see site.cfg.example for information. " + "to using a buggy Accelerate backend. If you compiled " + "yourself, more information is available at " + "https://numpy.org/doc/stable/user/building.html#accelerated-blas-lapack-libraries " "Otherwise report this to the vendor " - "that provided NumPy.\n{}\n".format( - error_message)) + "that provided NumPy.\n{}\n".format(error_message)) raise RuntimeError(msg) del _mac_os_check diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index c6c724ab3..d0ed3d381 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -1525,7 +1525,7 @@ add_newdoc('numpy.core.multiarray', 'c_einsum', Controls the memory layout of the output. 'C' means it should be C contiguous. 'F' means it should be Fortran contiguous, 'A' means it should be 'F' if the inputs are all 'F', 'C' otherwise. - 'K' means it should be as close to the layout as the inputs as + 'K' means it should be as close to the layout of the inputs as is possible, including arbitrarily permuted axes. Default is 'K'. casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional @@ -3936,18 +3936,17 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tobytes', """ Construct Python bytes containing the raw data bytes in the array. Constructs Python bytes showing a copy of the raw contents of - data memory. The bytes object can be produced in either 'C' or 'Fortran', - or 'Any' order (the default is 'C'-order). 'Any' order means C-order - unless the F_CONTIGUOUS flag in the array is set, in which case it - means 'Fortran' order. + data memory. The bytes object is produced in C-order by default. + This behavior is controlled by the ``order`` parameter. .. versionadded:: 1.9.0 Parameters ---------- - order : {'C', 'F', None}, optional - Order of the data for multidimensional arrays: - C, Fortran, or the same as for the original array. + order : {'C', 'F', 'A'}, optional + Controls the memory layout of the bytes object. 'C' means C-order, + 'F' means F-order, 'A' (short for *Any*) means 'F' if `a` is + Fortran contiguous, 'C' otherwise. Default is 'C'. Returns ------- diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src index 48e89915c..e6414e29e 100644 --- a/numpy/core/src/umath/simd.inc.src +++ b/numpy/core/src/umath/simd.inc.src @@ -2698,17 +2698,17 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void /* process elements using glibc for large elements */ if (my_trig_op == npy_compute_cos) { - for (int ii = 0; iglibc_mask != 0; ii++) { + for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) { if (iglibc_mask & 0x01) { - op[ii] = npy_cosf(ip[ii]); + op[ii] = npy_cosf(ip[jj]); } iglibc_mask = iglibc_mask >> 1; } } else { - for (int ii = 0; iglibc_mask != 0; ii++) { + for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) { if (iglibc_mask & 0x01) { - op[ii] = npy_sinf(ip[ii]); + op[ii] = npy_sinf(ip[jj]); } iglibc_mask = iglibc_mask >> 1; } diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 91acd6ac3..f836af168 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -890,15 +890,17 @@ class TestAVXFloat32Transcendental: sizes = np.arange(2,100) for ii in sizes: x_f32 = np.float32(np.random.uniform(low=0.01,high=88.1,size=ii)) + x_f32_large = x_f32.copy() + x_f32_large[3:-1:4] = 120000.0 exp_true = np.exp(x_f32) log_true = np.log(x_f32) - sin_true = np.sin(x_f32) - cos_true = np.cos(x_f32) + sin_true = np.sin(x_f32_large) + cos_true = np.cos(x_f32_large) for jj in strides: assert_array_almost_equal_nulp(np.exp(x_f32[::jj]), exp_true[::jj], nulp=2) assert_array_almost_equal_nulp(np.log(x_f32[::jj]), log_true[::jj], nulp=2) - assert_array_almost_equal_nulp(np.sin(x_f32[::jj]), sin_true[::jj], nulp=2) - assert_array_almost_equal_nulp(np.cos(x_f32[::jj]), cos_true[::jj], nulp=2) + assert_array_almost_equal_nulp(np.sin(x_f32_large[::jj]), sin_true[::jj], nulp=2) + assert_array_almost_equal_nulp(np.cos(x_f32_large[::jj]), cos_true[::jj], nulp=2) class TestLogAddExp(_FilterInvalids): def test_logaddexp_values(self): diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index f86ebf551..8ede29da1 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -244,11 +244,6 @@ class _fromnxfunction: the new masked array version of the function. A note on application of the function to the mask is appended. - .. warning:: - If the function docstring already contained a Notes section, the - new docstring will have two Notes sections instead of appending a note - to the existing section. - Parameters ---------- None @@ -258,9 +253,9 @@ class _fromnxfunction: doc = getattr(npfunc, '__doc__', None) if doc: sig = self.__name__ + ma.get_object_signature(npfunc) - locdoc = "Notes\n-----\nThe function is applied to both the _data"\ - " and the _mask, if any." - return '\n'.join((sig, doc, locdoc)) + doc = ma.doc_note(doc, "The function is applied to both the _data " + "and the _mask, if any.") + return '\n\n'.join((sig, doc)) return def __call__(self, *args, **params): diff --git a/site.cfg.example b/site.cfg.example index 3eba3bbd7..c809303a2 100644 --- a/site.cfg.example +++ b/site.cfg.example @@ -242,14 +242,6 @@ # library_dirs = C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2018\windows\mkl\lib\intel64 # libraries = mkl_rt -# Accelerate -# ---------- -# Accelerate/vecLib is an OSX framework providing a BLAS and LAPACK implementation. -# -# [accelerate] -# libraries = Accelerate, vecLib -# #libraries = None - # UMFPACK # ------- # The UMFPACK library is used in scikits.umfpack to factor large sparse matrices. |
