packages feed

hgeometry-combinatorial 0.10.0.0 → 0.14

raw patch · 71 files changed

Files

+ cbits/erf.c view
@@ -0,0 +1,97 @@+#include <math.h>++double erf_log(double number, double error, double result)+{+  long double precise = logl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_exp(double number, double error, double result)+{+  long double precise = expl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_pow(double n1, double e1, double n2, double e2, double result)+{+  long double precise = powl((long double)n1 + (long double)e1, (long double)n2 + (long double)e2);+  return (double) (precise - (long double)result);+}++double erf_sin(double number, double error, double result)+{+  long double precise = sinl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_cos(double number, double error, double result)+{+  long double precise = cosl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_tan(double number, double error, double result)+{+  long double precise = tanl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_asin(double number, double error, double result)+{+  long double precise = asinl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_acos(double number, double error, double result)+{+  long double precise = acosl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_atan(double number, double error, double result)+{+  long double precise = atanl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_sinh(double number, double error, double result)+{+  long double precise = sinhl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_cosh(double number, double error, double result)+{+  long double precise = coshl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_tanh(double number, double error, double result)+{+  long double precise = tanhl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_asinh(double number, double error, double result)+{+  long double precise = asinhl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_acosh(double number, double error, double result)+{+  long double precise = acoshl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_atanh(double number, double error, double result)+{+  long double precise = atanhl((long double)number + (long double)error);+  return (double) (precise - (long double)result);+}++double erf_atan2(double n1, double e1, double n2, double e2, double result)+{+  long double precise = atan2l((long double)n1 + (long double)e1, (long double)n2 + (long double)e2);+  return (double) (precise - (long double)result);+}
+ changelog view
@@ -0,0 +1,55 @@+#+STARTUP: showeverything++* Changelog++** 0.14++- Got rid of proxies to build planar graphs, use TypeApplication+  instead. Also slightly changed some of the types to better reflect+  what they need; in particular 'buildGraph' now takes only the+  adjacency lists (no face information). And 'fromAdjRep' which+  computes a PlanarGraph from its adjacencylists (including vertex and+  edge info.)+- Cleaning up the public API by hiding several internal modules.++** 0.13++- Moved 'intersects' from the HasIntersectionWith class into a new+  class IsIntersectableWith. This allows separate (weaker) constraints+  for checking *if* geometries intersect rather than computing exact+  intersections.+- Bug fixes in the orientations of boundaries in PlanarGraph.+- Implementation of Logaritmic Method, wich allows us to transform a+  static data structure into an insertion only data structure++** 0.12++- Add Data.Double.Approximate: Floating point numbers take take+  imprecision into account when ordering.+- Add Data.Double.Shaman: Floating point numbers that keep track of+  error bounds while not being more than an order of magnitude slower+  than native floating point numbers.+- Add Data.PlanarGraph.Immutable and Data.PlanarGraph.Mutable: New+  planargraph implementation that supports efficient updates and queries.++** 0.11++- Changed the implementation of Two and Three in Data.Util+  (hgeometry-combinatorial). Now they have proper Functor, Foldable,+  and Traversable instances.+- Added Data.RealNumber.Rational wrapping the Rational type giving+  some more readable show/read instances+- Added function to compute levels in a Rose-Tree+- Moved the binary searching functions from Data.Sequence.Util into+  Algorithms.BinarySearch, also added a version for fractional types+  that stops at a given threshold.+- Removed Data.BalBST and Data.SlowSeq+- Moved Measured from Data.BinaryTree into a separate module.++** 0.10++- More Instances++** 0.9++- First release in which hgeometry-combinatorial was split off from hgeometry.
changelog.org view
@@ -0,0 +1,55 @@+#+STARTUP: showeverything++* Changelog++** 0.14++- Got rid of proxies to build planar graphs, use TypeApplication+  instead. Also slightly changed some of the types to better reflect+  what they need; in particular 'buildGraph' now takes only the+  adjacency lists (no face information). And 'fromAdjRep' which+  computes a PlanarGraph from its adjacencylists (including vertex and+  edge info.)+- Cleaning up the public API by hiding several internal modules.++** 0.13++- Moved 'intersects' from the HasIntersectionWith class into a new+  class IsIntersectableWith. This allows separate (weaker) constraints+  for checking *if* geometries intersect rather than computing exact+  intersections.+- Bug fixes in the orientations of boundaries in PlanarGraph.+- Implementation of Logaritmic Method, wich allows us to transform a+  static data structure into an insertion only data structure++** 0.12++- Add Data.Double.Approximate: Floating point numbers take take+  imprecision into account when ordering.+- Add Data.Double.Shaman: Floating point numbers that keep track of+  error bounds while not being more than an order of magnitude slower+  than native floating point numbers.+- Add Data.PlanarGraph.Immutable and Data.PlanarGraph.Mutable: New+  planargraph implementation that supports efficient updates and queries.++** 0.11++- Changed the implementation of Two and Three in Data.Util+  (hgeometry-combinatorial). Now they have proper Functor, Foldable,+  and Traversable instances.+- Added Data.RealNumber.Rational wrapping the Rational type giving+  some more readable show/read instances+- Added function to compute levels in a Rose-Tree+- Moved the binary searching functions from Data.Sequence.Util into+  Algorithms.BinarySearch, also added a version for fractional types+  that stops at a given threshold.+- Removed Data.BalBST and Data.SlowSeq+- Moved Measured from Data.BinaryTree into a separate module.++** 0.10++- More Instances++** 0.9++- First release in which hgeometry-combinatorial was split off from hgeometry.
+ docs/Data/PlanarGraph/planargraph-1711135548958680232.svg view
@@ -0,0 +1,199 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(0, 1.2)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -1.2)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.09863, 0)">+              <line x2="0.197261" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+        <g transform="translate(-2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" y1="-0" x2="-3.6" y2="0" />+        <g transform="translate(-1.8, -0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.8, 0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.6" y1="-0" y2="-0" />+        <g transform="translate(1.8, -0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.8, 0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+        <g transform="translate(2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.269489, -0.325778)">+              <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+        <g transform="translate(2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+        <g transform="translate(-2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.502118, -0.331756)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.522541, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.6, 0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(0, -0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.6, -0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.483734)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.45316)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-1902492848341357096.svg view
@@ -0,0 +1,166 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(0, 1.2)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -1.2)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.09863, 0)">+              <line x2="0.197261" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+        <g transform="translate(-2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+        <g transform="translate(-2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+        <g transform="translate(2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+        <g transform="translate(2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.269489, -0.325778)">+              <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.6" y1="-0" x2="-3.6" y2="0" />+        <g transform="translate(-0, -0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(0, 0.3)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.6, 0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.6, -0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.483734)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2506803680640023584.svg view
@@ -0,0 +1,135 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(-0, 0)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.6" y1="0" x2="0" y2="3.6" />+        <g transform="translate(-2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-3.6" x2="-3.6" y2="0" />+        <g transform="translate(-2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.6" y1="-0" x2="-0" y2="-3.6" />+        <g transform="translate(2.012132, -2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, -1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.6" y2="-0" />+        <g transform="translate(2.012132, 2.012132)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.269489, -0.325778)">+              <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.587868, 1.587868)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.6, 0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.6, -0)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.483734)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg view
@@ -0,0 +1,193 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(-1.247077, 0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, 1.44)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.09863, 0)">+              <line x2="0.197261" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-1.247077, -0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.119253, 0)">+              <line x2="0.238506" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -1.44)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.124035, 0)">+              <line x2="0.24807" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(1.247077, -0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.218618)" fill-opacity="0">+            <g transform="translate(-0.132403, 0)">+              <line x2="0.264807" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(1.247077, 0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.119253, 0)">+              <line x2="0.238506" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+      </g>+      <g>+        <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-3.117691" y2="-1.8" />+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="-0.623538" y2="0.36" />+      </g>+      <g>+        <line stroke="#000000" x1="0.623538" y1="0.36" x2="-0.623538" y2="0.36" />+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="0.623538" y2="0.36" />+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="-3.117691" y2="-1.8" />+      </g>+      <g>+        <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-0" y2="-0.72" />+      </g>+      <g>+        <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="3.117691" y2="-1.8" />+      </g>+      <g>+        <line stroke="#000000" x1="0.623538" y1="0.36" x2="3.117691" y2="-1.8" />+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="0.623538" y2="0.36" />+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0.623538, 0.36)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(0.623538, 0.36)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -0.72)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.483734)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.45316)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2635031442529484236.svg view
@@ -0,0 +1,403 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(-1.247077, 0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, 1.44)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.09863, 0)">+              <line x2="0.197261" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-1.247077, -0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.215878)" fill-opacity="0">+            <g transform="translate(-0.119253, 0)">+              <line x2="0.238506" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -1.44)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.124035, 0)">+              <line x2="0.24807" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(1.247077, -0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.218618)" fill-opacity="0">+            <g transform="translate(-0.132403, 0)">+              <line x2="0.264807" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(1.247077, 0.72)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.119253, 0)">+              <line x2="0.238506" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+        <g transform="translate(-1.818653, 1.05)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.299038, 0.75)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-3.117691" y2="-1.8" />+        <g transform="translate(-1.674219, -0.946779)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-2.067011, -0.493221)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="-0.623538" y2="0.36" />+        <g transform="translate(-0.017175, 1.923305)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-0.606363, 2.036695)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0.623538" y1="0.36" x2="-0.623538" y2="0.36" />+        <g transform="translate(-0, 0.06)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.269489, -0.325778)">+              <path d="M0.474222,0.606725 C0.483188,0.61868 0.483188,0.620672 0.483188,0.641594 L0.241096,0.641594 C0.119552,0.641594 0.117559,0.654545 0.113574,0.673474 L0.088667,0.673474 L0.055791,0.468244 L0.080697,0.468244 C0.083686,0.484184 0.092653,0.546949 0.105604,0.558904 C0.112578,0.564882 0.190286,0.564882 0.203238,0.564882 L0.409465,0.564882 C0.398506,0.548941 0.319801,0.440349 0.297883,0.407472 C0.208219,0.272976 0.175342,0.134496 0.175342,0.032877 C0.175342,0.022914 0.175342,-0.021918 0.221171,-0.021918 C0.267,-0.021918 0.266999,0.022914 0.266999,0.032877 L0.266999,0.083686 C0.266999,0.138481 0.269988,0.193275 0.277958,0.247073 C0.281943,0.269988 0.29589,0.355666 0.339726,0.417435 L0.474222,0.606725 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-0, 0.66)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.131507,0.326775 L0.131507,0.350685 C0.131507,0.60274 0.255044,0.638605 0.305853,0.638605 C0.329763,0.638605 0.371606,0.632628 0.393524,0.598755 C0.37858,0.598755 0.33873,0.598755 0.33873,0.553923 C0.33873,0.523039 0.36264,0.508095 0.384558,0.508095 C0.400498,0.508095 0.430386,0.517061 0.430386,0.555915 C0.430386,0.615691 0.38655,0.663512 0.303861,0.663512 C0.176339,0.663512 0.041843,0.534994 0.041843,0.314819 C0.041843,0.048817 0.15741,-0.021918 0.250062,-0.021918 C0.360648,-0.021918 0.455293,0.071731 0.455293,0.203238 C0.455293,0.329763 0.366625,0.425405 0.25604,0.425405 C0.188294,0.425405 0.151432,0.374595 0.131507,0.326775 Z M0.250062,0.005978 C0.187298,0.005978 0.15741,0.065753 0.151432,0.080697 C0.133499,0.127522 0.133499,0.207223 0.133499,0.225156 C0.133499,0.302864 0.16538,0.402491 0.255044,0.402491 C0.270984,0.402491 0.316812,0.402491 0.347696,0.340722 C0.365629,0.303861 0.365629,0.253051 0.365629,0.204234 C0.365629,0.156413 0.365629,0.1066 0.348692,0.070735 C0.318804,0.010959 0.272976,0.005978 0.250062,0.005978 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="0.623538" y2="0.36" />+        <g transform="translate(0.606363, 2.036695)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.365629,0.316812 L0.365629,0.284932 C0.365629,0.051806 0.262017,0.005978 0.204234,0.005978 C0.187298,0.005978 0.133499,0.00797 0.1066,0.041843 C0.150436,0.041843 0.158406,0.070735 0.158406,0.087671 C0.158406,0.118555 0.134496,0.133499 0.112578,0.133499 C0.096638,0.133499 0.06675,0.124533 0.06675,0.085679 C0.06675,0.018929 0.120548,-0.021918 0.20523,-0.021918 C0.333748,-0.021918 0.455293,0.113574 0.455293,0.327771 C0.455293,0.595766 0.340722,0.663512 0.252055,0.663512 C0.19726,0.663512 0.148443,0.645579 0.105604,0.600747 C0.064757,0.555915 0.041843,0.514072 0.041843,0.439352 C0.041843,0.314819 0.129514,0.217186 0.241096,0.217186 C0.301868,0.217186 0.342715,0.259029 0.365629,0.316812 Z M0.242092,0.2401 C0.226152,0.2401 0.180324,0.2401 0.14944,0.302864 C0.131507,0.339726 0.131507,0.389539 0.131507,0.438356 C0.131507,0.492154 0.131507,0.538979 0.152428,0.575841 C0.179328,0.625654 0.217186,0.638605 0.252055,0.638605 C0.297883,0.638605 0.33076,0.604732 0.347696,0.5599 C0.359651,0.52802 0.363636,0.465255 0.363636,0.419427 C0.363636,0.336737 0.329763,0.2401 0.242092,0.2401 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(0.017175, 1.923305)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.162391,0.455293 C0.116563,0.485181 0.112578,0.519054 0.112578,0.53599 C0.112578,0.596762 0.177335,0.638605 0.24807,0.638605 C0.320797,0.638605 0.384558,0.5868 0.384558,0.515068 C0.384558,0.458281 0.345704,0.410461 0.285928,0.375592 L0.162391,0.455293 Z M0.307846,0.360648 C0.379577,0.397509 0.428394,0.449315 0.428394,0.515068 C0.428394,0.606725 0.339726,0.663512 0.249066,0.663512 C0.14944,0.663512 0.068742,0.589788 0.068742,0.497136 C0.068742,0.479203 0.070735,0.434371 0.112578,0.387547 C0.123537,0.375592 0.160399,0.350685 0.185305,0.333748 C0.127522,0.304857 0.041843,0.249066 0.041843,0.150436 C0.041843,0.044832 0.143462,-0.021918 0.24807,-0.021918 C0.360648,-0.021918 0.455293,0.060772 0.455293,0.167372 C0.455293,0.203238 0.444334,0.24807 0.406476,0.289913 C0.387547,0.310834 0.371606,0.320797 0.307846,0.360648 Z M0.208219,0.318804 L0.33076,0.241096 C0.358655,0.222167 0.405479,0.192279 0.405479,0.131507 C0.405479,0.057783 0.33076,0.005978 0.249066,0.005978 C0.163387,0.005978 0.091656,0.067746 0.091656,0.150436 C0.091656,0.208219 0.123537,0.27198 0.208219,0.318804 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="-3.117691" y2="-1.8" />+        <g transform="translate(-1.460648, -1.543473)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.502118, -0.331756)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(-1.657044, -0.976527)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.522541, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0.623538" y1="0.36" x2="-0" y2="-0.72" />+        <g transform="translate(-0.051962, -0.03)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.521047, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.787051,0.350685 C0.868744,0.377584 0.926528,0.447323 0.926528,0.526027 C0.926528,0.607721 0.838856,0.663512 0.743215,0.663512 C0.642592,0.663512 0.566876,0.603736 0.566876,0.52802 C0.566876,0.495143 0.588794,0.476214 0.617686,0.476214 C0.64857,0.476214 0.668495,0.498132 0.668495,0.527024 C0.668495,0.576837 0.621671,0.576837 0.606727,0.576837 C0.637611,0.625654 0.703364,0.638605 0.73923,0.638605 C0.780077,0.638605 0.834871,0.616687 0.834871,0.527024 C0.834871,0.515068 0.832879,0.457285 0.806976,0.41345 C0.777088,0.365629 0.743215,0.36264 0.718308,0.361644 C0.710338,0.360648 0.686428,0.358655 0.679454,0.358655 C0.671484,0.357659 0.66451,0.356663 0.66451,0.3467 C0.66451,0.335741 0.671484,0.335741 0.68842,0.335741 L0.732256,0.335741 C0.81395,0.335741 0.850811,0.267995 0.850811,0.170361 C0.850811,0.034869 0.782069,0.005978 0.738234,0.005978 C0.695394,0.005978 0.620674,0.022914 0.585805,0.081694 C0.620674,0.076712 0.651559,0.09863 0.651559,0.136488 C0.651559,0.172354 0.62466,0.192279 0.595768,0.192279 C0.571858,0.192279 0.539977,0.178331 0.539977,0.134496 C0.539977,0.043836 0.63263,-0.021918 0.741222,-0.021918 C0.862767,-0.021918 0.953427,0.068742 0.953427,0.170361 C0.953427,0.252055 0.890662,0.329763 0.787051,0.350685 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(-0.571577, -0.33)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.517062, -0.331756)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.62466,0.076712 L0.730264,0.179328 C0.885681,0.316812 0.945457,0.37061 0.945457,0.470237 C0.945457,0.583811 0.855793,0.663512 0.734249,0.663512 C0.621671,0.663512 0.547947,0.571856 0.547947,0.483188 C0.547947,0.427397 0.59776,0.427397 0.600749,0.427397 C0.617686,0.427397 0.652555,0.439352 0.652555,0.480199 C0.652555,0.506102 0.634622,0.532005 0.599753,0.532005 C0.591783,0.532005 0.58979,0.532005 0.586801,0.531009 C0.609716,0.595766 0.663514,0.632628 0.721297,0.632628 C0.811957,0.632628 0.854797,0.55193 0.854797,0.470237 C0.854797,0.390535 0.804983,0.311831 0.750189,0.250062 L0.558906,0.036862 C0.547947,0.025903 0.547947,0.02391 0.547947,0 L0.917561,0 L0.945457,0.17335 L0.92055,0.17335 C0.915569,0.143462 0.908595,0.099626 0.898632,0.084682 C0.891658,0.076712 0.825905,0.076712 0.803987,0.076712 L0.62466,0.076712 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+        <g transform="translate(-0, -2.1)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.517062, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.945457,0.200249 C0.945457,0.318804 0.863763,0.418431 0.756166,0.418431 C0.708346,0.418431 0.665506,0.402491 0.629641,0.367621 L0.629641,0.561893 C0.649566,0.555915 0.682443,0.548941 0.714323,0.548941 C0.836864,0.548941 0.906602,0.639601 0.906602,0.652553 C0.906602,0.658531 0.903613,0.663512 0.89664,0.663512 C0.895643,0.663512 0.893651,0.663512 0.888669,0.660523 C0.868744,0.651557 0.819927,0.631631 0.753178,0.631631 C0.713327,0.631631 0.667499,0.638605 0.620674,0.659527 C0.612704,0.662516 0.610712,0.662516 0.608719,0.662516 C0.598757,0.662516 0.598757,0.654545 0.598757,0.638605 L0.598757,0.343711 C0.598757,0.325778 0.598757,0.317808 0.612704,0.317808 C0.619678,0.317808 0.621671,0.320797 0.625656,0.326775 C0.636615,0.342715 0.673476,0.396513 0.754174,0.396513 C0.80598,0.396513 0.830886,0.350685 0.838856,0.332752 C0.854797,0.29589 0.856789,0.257036 0.856789,0.207223 C0.856789,0.172354 0.856789,0.112578 0.832879,0.070735 C0.808968,0.03188 0.772107,0.005978 0.726278,0.005978 C0.653551,0.005978 0.596764,0.05878 0.579828,0.117559 C0.582816,0.116563 0.585805,0.115567 0.596764,0.115567 C0.629641,0.115567 0.646577,0.140473 0.646577,0.164384 C0.646577,0.188295 0.629641,0.2132 0.596764,0.2132 C0.582816,0.2132 0.547947,0.206227 0.547947,0.160399 C0.547947,0.07472 0.616689,-0.021918 0.728271,-0.021918 C0.843838,-0.021918 0.945457,0.073724 0.945457,0.200249 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(-0, -1.5)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.528021, -0.337236)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.791036,0.164384 L0.791036,0.077709 C0.791036,0.041843 0.789043,0.030884 0.71532,0.030884 L0.694398,0.030884 L0.694398,0 C0.735245,0.002989 0.787051,0.002989 0.828894,0.002989 C0.870737,0.002989 0.923539,0.002989 0.964386,0 L0.964386,0.030884 L0.943464,0.030884 C0.86974,0.030884 0.867748,0.041843 0.867748,0.077709 L0.867748,0.164384 L0.967374,0.164384 L0.967374,0.195268 L0.867748,0.195268 L0.867748,0.648568 C0.867748,0.668493 0.867748,0.674471 0.851808,0.674471 C0.842841,0.674471 0.839853,0.674471 0.831882,0.662516 L0.526029,0.195268 L0.526029,0.164384 L0.791036,0.164384 Z M0.797013,0.195268 L0.553925,0.195268 L0.797013,0.566874 L0.797013,0.195268 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="3.117691" y2="-1.8" />+        <g transform="translate(1.657044, -0.976527)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.534995, -0.325778)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.972356,0.606725 C0.981322,0.61868 0.981322,0.620672 0.981322,0.641594 L0.73923,0.641594 C0.617686,0.641594 0.615693,0.654545 0.611708,0.673474 L0.586801,0.673474 L0.553925,0.468244 L0.578831,0.468244 C0.58182,0.484184 0.590787,0.546949 0.603738,0.558904 C0.610712,0.564882 0.68842,0.564882 0.701372,0.564882 L0.907599,0.564882 C0.89664,0.548941 0.817935,0.440349 0.796017,0.407472 C0.706353,0.272976 0.673476,0.134496 0.673476,0.032877 C0.673476,0.022914 0.673476,-0.021918 0.719305,-0.021918 C0.765134,-0.021918 0.765133,0.022914 0.765133,0.032877 L0.765133,0.083686 C0.765133,0.138481 0.768122,0.193275 0.776092,0.247073 C0.780077,0.269988 0.794024,0.355666 0.83786,0.417435 L0.972356,0.606725 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(1.460648, -1.543473)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.521047, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.629641,0.326775 L0.629641,0.350685 C0.629641,0.60274 0.753178,0.638605 0.803987,0.638605 C0.827897,0.638605 0.86974,0.632628 0.891658,0.598755 C0.876714,0.598755 0.836864,0.598755 0.836864,0.553923 C0.836864,0.523039 0.860774,0.508095 0.882692,0.508095 C0.898632,0.508095 0.92852,0.517061 0.92852,0.555915 C0.92852,0.615691 0.884684,0.663512 0.801995,0.663512 C0.674473,0.663512 0.539977,0.534994 0.539977,0.314819 C0.539977,0.048817 0.655544,-0.021918 0.748196,-0.021918 C0.858782,-0.021918 0.953427,0.071731 0.953427,0.203238 C0.953427,0.329763 0.864759,0.425405 0.754174,0.425405 C0.686428,0.425405 0.649566,0.374595 0.629641,0.326775 Z M0.748196,0.005978 C0.685432,0.005978 0.655544,0.065753 0.649566,0.080697 C0.631633,0.127522 0.631633,0.207223 0.631633,0.225156 C0.631633,0.302864 0.663514,0.402491 0.753178,0.402491 C0.769118,0.402491 0.814946,0.402491 0.84583,0.340722 C0.863763,0.303861 0.863763,0.253051 0.863763,0.204234 C0.863763,0.156413 0.863763,0.1066 0.846826,0.070735 C0.816938,0.010959 0.77111,0.005978 0.748196,0.005978 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0.623538" y1="0.36" x2="3.117691" y2="-1.8" />+        <g transform="translate(2.067011, -0.493221)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.521047, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.863763,0.316812 L0.863763,0.284932 C0.863763,0.051806 0.760151,0.005978 0.702368,0.005978 C0.685432,0.005978 0.631633,0.00797 0.604734,0.041843 C0.64857,0.041843 0.65654,0.070735 0.65654,0.087671 C0.65654,0.118555 0.63263,0.133499 0.610712,0.133499 C0.594772,0.133499 0.564884,0.124533 0.564884,0.085679 C0.564884,0.018929 0.618682,-0.021918 0.703364,-0.021918 C0.831882,-0.021918 0.953427,0.113574 0.953427,0.327771 C0.953427,0.595766 0.838856,0.663512 0.750189,0.663512 C0.695394,0.663512 0.646577,0.645579 0.603738,0.600747 C0.562891,0.555915 0.539977,0.514072 0.539977,0.439352 C0.539977,0.314819 0.627648,0.217186 0.73923,0.217186 C0.800002,0.217186 0.840849,0.259029 0.863763,0.316812 Z M0.740226,0.2401 C0.724286,0.2401 0.678458,0.2401 0.647574,0.302864 C0.629641,0.339726 0.629641,0.389539 0.629641,0.438356 C0.629641,0.492154 0.629641,0.538979 0.650562,0.575841 C0.677462,0.625654 0.71532,0.638605 0.750189,0.638605 C0.796017,0.638605 0.828894,0.604732 0.84583,0.5599 C0.857785,0.52802 0.86177,0.465255 0.86177,0.419427 C0.86177,0.336737 0.827897,0.2401 0.740226,0.2401 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(1.674219, -0.946779)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.521047, -0.320797)">+              <g>+                <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+                <path d="M0.660525,0.455293 C0.614697,0.485181 0.610712,0.519054 0.610712,0.53599 C0.610712,0.596762 0.675469,0.638605 0.746204,0.638605 C0.818931,0.638605 0.882692,0.5868 0.882692,0.515068 C0.882692,0.458281 0.843838,0.410461 0.784062,0.375592 L0.660525,0.455293 Z M0.80598,0.360648 C0.877711,0.397509 0.926528,0.449315 0.926528,0.515068 C0.926528,0.606725 0.83786,0.663512 0.7472,0.663512 C0.647574,0.663512 0.566876,0.589788 0.566876,0.497136 C0.566876,0.479203 0.568869,0.434371 0.610712,0.387547 C0.621671,0.375592 0.658533,0.350685 0.683439,0.333748 C0.625656,0.304857 0.539977,0.249066 0.539977,0.150436 C0.539977,0.044832 0.641596,-0.021918 0.746204,-0.021918 C0.858782,-0.021918 0.953427,0.060772 0.953427,0.167372 C0.953427,0.203238 0.942468,0.24807 0.90461,0.289913 C0.885681,0.310834 0.86974,0.320797 0.80598,0.360648 Z M0.706353,0.318804 L0.828894,0.241096 C0.856789,0.222167 0.903613,0.192279 0.903613,0.131507 C0.903613,0.057783 0.828894,0.005978 0.7472,0.005978 C0.661521,0.005978 0.58979,0.067746 0.58979,0.150436 C0.58979,0.208219 0.621671,0.27198 0.706353,0.318804 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="-0" y1="-0.72" x2="0.623538" y2="0.36" />+        <g transform="translate(0.051962, -0.03)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.482691, -0.331756)">+              <g>+                <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+                <path d="M0.791036,0.637609 C0.791036,0.661519 0.791036,0.663512 0.768122,0.663512 C0.706353,0.599751 0.618682,0.599751 0.586801,0.599751 L0.586801,0.568867 C0.606727,0.568867 0.665506,0.568867 0.717312,0.59477 L0.717312,0.078705 C0.717312,0.042839 0.714323,0.030884 0.62466,0.030884 L0.592779,0.030884 L0.592779,0 C0.627648,0.002989 0.714323,0.002989 0.754174,0.002989 C0.794025,0.002989 0.880699,0.002989 0.915569,0 L0.915569,0.030884 L0.883688,0.030884 C0.794024,0.030884 0.791036,0.041843 0.791036,0.078705 L0.791036,0.637609 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(0.571577, -0.33)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.503114, -0.320797)">+              <g>+                <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+                <path d="M0.956415,0.318804 C0.956415,0.398506 0.951434,0.478207 0.916565,0.55193 C0.870737,0.647572 0.789043,0.663512 0.7472,0.663512 C0.687424,0.663512 0.614697,0.637609 0.57385,0.544956 C0.54197,0.476214 0.536988,0.398506 0.536988,0.318804 C0.536988,0.244085 0.540973,0.154421 0.58182,0.078705 C0.62466,-0.001993 0.697387,-0.021918 0.746204,-0.021918 C0.800002,-0.021918 0.875718,-0.000996 0.919554,0.093649 C0.951434,0.162391 0.956415,0.2401 0.956415,0.318804 Z M0.746204,0 C0.707349,0 0.64857,0.024907 0.630637,0.120548 C0.619678,0.180324 0.619678,0.27198 0.619678,0.33076 C0.619678,0.394521 0.619678,0.460274 0.627648,0.514072 C0.646577,0.632628 0.721297,0.641594 0.746204,0.641594 C0.77908,0.641594 0.844834,0.623661 0.863763,0.525031 C0.873726,0.46924 0.873726,0.393524 0.873726,0.33076 C0.873726,0.25604 0.873726,0.188294 0.862767,0.124533 C0.847823,0.029888 0.791036,0 0.746204,0 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+        <g transform="translate(1.818653, 1.05)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.50162, -0.320797)">+              <g>+                <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+                <path d="M0.787051,0.350685 C0.868744,0.377584 0.926528,0.447323 0.926528,0.526027 C0.926528,0.607721 0.838856,0.663512 0.743215,0.663512 C0.642592,0.663512 0.566876,0.603736 0.566876,0.52802 C0.566876,0.495143 0.588794,0.476214 0.617686,0.476214 C0.64857,0.476214 0.668495,0.498132 0.668495,0.527024 C0.668495,0.576837 0.621671,0.576837 0.606727,0.576837 C0.637611,0.625654 0.703364,0.638605 0.73923,0.638605 C0.780077,0.638605 0.834871,0.616687 0.834871,0.527024 C0.834871,0.515068 0.832879,0.457285 0.806976,0.41345 C0.777088,0.365629 0.743215,0.36264 0.718308,0.361644 C0.710338,0.360648 0.686428,0.358655 0.679454,0.358655 C0.671484,0.357659 0.66451,0.356663 0.66451,0.3467 C0.66451,0.335741 0.671484,0.335741 0.68842,0.335741 L0.732256,0.335741 C0.81395,0.335741 0.850811,0.267995 0.850811,0.170361 C0.850811,0.034869 0.782069,0.005978 0.738234,0.005978 C0.695394,0.005978 0.620674,0.022914 0.585805,0.081694 C0.620674,0.076712 0.651559,0.09863 0.651559,0.136488 C0.651559,0.172354 0.62466,0.192279 0.595768,0.192279 C0.571858,0.192279 0.539977,0.178331 0.539977,0.134496 C0.539977,0.043836 0.63263,-0.021918 0.741222,-0.021918 C0.862767,-0.021918 0.953427,0.068742 0.953427,0.170361 C0.953427,0.252055 0.890662,0.329763 0.787051,0.350685 Z" />+              </g>+            </g>+          </g>+        </g>+        <g transform="translate(1.299038, 0.75)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.497635, -0.331756)">+              <g>+                <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+                <path d="M0.62466,0.076712 L0.730264,0.179328 C0.885681,0.316812 0.945457,0.37061 0.945457,0.470237 C0.945457,0.583811 0.855793,0.663512 0.734249,0.663512 C0.621671,0.663512 0.547947,0.571856 0.547947,0.483188 C0.547947,0.427397 0.59776,0.427397 0.600749,0.427397 C0.617686,0.427397 0.652555,0.439352 0.652555,0.480199 C0.652555,0.506102 0.634622,0.532005 0.599753,0.532005 C0.591783,0.532005 0.58979,0.532005 0.586801,0.531009 C0.609716,0.595766 0.663514,0.632628 0.721297,0.632628 C0.811957,0.632628 0.854797,0.55193 0.854797,0.470237 C0.854797,0.390535 0.804983,0.311831 0.750189,0.250062 L0.558906,0.036862 C0.547947,0.025903 0.547947,0.02391 0.547947,0 L0.917561,0 L0.945457,0.17335 L0.92055,0.17335 C0.915569,0.143462 0.908595,0.099626 0.898632,0.084682 C0.891658,0.076712 0.825905,0.076712 0.803987,0.076712 L0.62466,0.076712 Z" />+              </g>+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0.623538, 0.36)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(0.623538, 0.36)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-0, -0.72)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.483734)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.45316)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
+ docs/Data/PlanarGraph/planargraph-2959979592048325618.svg view
@@ -0,0 +1,108 @@+<svg viewBox="-8 -4.5 16 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="300" height="300" preserveAspectRatio="none"><g stroke-width="0.05" transform="scale(1, -1)"><g transform="translate(-8, -4.5)"><svg viewBox="-4.5 -4.5 9 9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="16" height="9" preserveAspectRatio="none">+  <g>+    <g stroke-width="0" fill="#FFFFFF" transform="translate(-8, -4.5)" fill-opacity="1">+      <rect width="16" height="9" />+    </g>+    <g>+      <g transform="translate(-0, -0)">+        <g>+          <g transform="scale(0.5)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+          <g stroke-width="0.025" stroke="#000000" transform="translate(0, -0.221357)" fill-opacity="0">+            <g transform="translate(-0.125828, 0)">+              <line x2="0.251656" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g>+        <line stroke="#000000" x1="-3.117691" y1="-1.8" x2="0" y2="3.6" />+        <g transform="translate(-1.818653, 1.05)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-1.299038, 0.75)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="3.117691" y1="-1.8" x2="-3.117691" y2="-1.8" />+        <g transform="translate(-0, -2.1)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.288917,0.350685 C0.37061,0.377584 0.428394,0.447323 0.428394,0.526027 C0.428394,0.607721 0.340722,0.663512 0.245081,0.663512 C0.144458,0.663512 0.068742,0.603736 0.068742,0.52802 C0.068742,0.495143 0.09066,0.476214 0.119552,0.476214 C0.150436,0.476214 0.170361,0.498132 0.170361,0.527024 C0.170361,0.576837 0.123537,0.576837 0.108593,0.576837 C0.139477,0.625654 0.20523,0.638605 0.241096,0.638605 C0.281943,0.638605 0.336737,0.616687 0.336737,0.527024 C0.336737,0.515068 0.334745,0.457285 0.308842,0.41345 C0.278954,0.365629 0.245081,0.36264 0.220174,0.361644 C0.212204,0.360648 0.188294,0.358655 0.18132,0.358655 C0.17335,0.357659 0.166376,0.356663 0.166376,0.3467 C0.166376,0.335741 0.17335,0.335741 0.190286,0.335741 L0.234122,0.335741 C0.315816,0.335741 0.352677,0.267995 0.352677,0.170361 C0.352677,0.034869 0.283935,0.005978 0.2401,0.005978 C0.19726,0.005978 0.12254,0.022914 0.087671,0.081694 C0.12254,0.076712 0.153425,0.09863 0.153425,0.136488 C0.153425,0.172354 0.126526,0.192279 0.097634,0.192279 C0.073724,0.192279 0.041843,0.178331 0.041843,0.134496 C0.041843,0.043836 0.134496,-0.021918 0.243088,-0.021918 C0.364633,-0.021918 0.455293,0.068742 0.455293,0.170361 C0.455293,0.252055 0.392528,0.329763 0.288917,0.350685 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(-0, -1.5)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+      <g>+        <line stroke="#000000" x1="0" y1="3.6" x2="3.117691" y2="-1.8" />+        <g transform="translate(1.818653, 1.05)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248568, -0.320797)">+              <path d="M0.447323,0.200249 C0.447323,0.318804 0.365629,0.418431 0.258032,0.418431 C0.210212,0.418431 0.167372,0.402491 0.131507,0.367621 L0.131507,0.561893 C0.151432,0.555915 0.184309,0.548941 0.216189,0.548941 C0.33873,0.548941 0.408468,0.639601 0.408468,0.652553 C0.408468,0.658531 0.405479,0.663512 0.398506,0.663512 C0.397509,0.663512 0.395517,0.663512 0.390535,0.660523 C0.37061,0.651557 0.321793,0.631631 0.255044,0.631631 C0.215193,0.631631 0.169365,0.638605 0.12254,0.659527 C0.11457,0.662516 0.112578,0.662516 0.110585,0.662516 C0.100623,0.662516 0.100623,0.654545 0.100623,0.638605 L0.100623,0.343711 C0.100623,0.325778 0.100623,0.317808 0.11457,0.317808 C0.121544,0.317808 0.123537,0.320797 0.127522,0.326775 C0.138481,0.342715 0.175342,0.396513 0.25604,0.396513 C0.307846,0.396513 0.332752,0.350685 0.340722,0.332752 C0.356663,0.29589 0.358655,0.257036 0.358655,0.207223 C0.358655,0.172354 0.358655,0.112578 0.334745,0.070735 C0.310834,0.03188 0.273973,0.005978 0.228144,0.005978 C0.155417,0.005978 0.09863,0.05878 0.081694,0.117559 C0.084682,0.116563 0.087671,0.115567 0.09863,0.115567 C0.131507,0.115567 0.148443,0.140473 0.148443,0.164384 C0.148443,0.188295 0.131507,0.2132 0.09863,0.2132 C0.084682,0.2132 0.049813,0.206227 0.049813,0.160399 C0.049813,0.07472 0.118555,-0.021918 0.230137,-0.021918 C0.345704,-0.021918 0.447323,0.073724 0.447323,0.200249 Z" />+            </g>+          </g>+        </g>+        <g transform="translate(1.299038, 0.75)">+          <g transform="scale(0.4)">+            <g transform="translate(-0.248567, -0.337236)">+              <path d="M0.292902,0.164384 L0.292902,0.077709 C0.292902,0.041843 0.290909,0.030884 0.217186,0.030884 L0.196264,0.030884 L0.196264,0 C0.237111,0.002989 0.288917,0.002989 0.33076,0.002989 C0.372603,0.002989 0.425405,0.002989 0.466252,0 L0.466252,0.030884 L0.44533,0.030884 C0.371606,0.030884 0.369614,0.041843 0.369614,0.077709 L0.369614,0.164384 L0.46924,0.164384 L0.46924,0.195268 L0.369614,0.195268 L0.369614,0.648568 C0.369614,0.668493 0.369614,0.674471 0.353674,0.674471 C0.344707,0.674471 0.341719,0.674471 0.333748,0.662516 L0.027895,0.195268 L0.027895,0.164384 L0.292902,0.164384 Z M0.298879,0.195268 L0.055791,0.195268 L0.298879,0.566874 L0.298879,0.195268 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+    <g>+      <g transform="translate(0, 3.6)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.476841)">+            <g transform="translate(-0.248567, -0.320797)">+              <path d="M0.458281,0.318804 C0.458281,0.398506 0.4533,0.478207 0.418431,0.55193 C0.372603,0.647572 0.290909,0.663512 0.249066,0.663512 C0.18929,0.663512 0.116563,0.637609 0.075716,0.544956 C0.043836,0.476214 0.038854,0.398506 0.038854,0.318804 C0.038854,0.244085 0.042839,0.154421 0.083686,0.078705 C0.126526,-0.001993 0.199253,-0.021918 0.24807,-0.021918 C0.301868,-0.021918 0.377584,-0.000996 0.42142,0.093649 C0.4533,0.162391 0.458281,0.2401 0.458281,0.318804 Z M0.24807,0 C0.209215,0 0.150436,0.024907 0.132503,0.120548 C0.121544,0.180324 0.121544,0.27198 0.121544,0.33076 C0.121544,0.394521 0.121544,0.460274 0.129514,0.514072 C0.148443,0.632628 0.223163,0.641594 0.24807,0.641594 C0.280946,0.641594 0.3467,0.623661 0.365629,0.525031 C0.375592,0.46924 0.375592,0.393524 0.375592,0.33076 C0.375592,0.25604 0.375592,0.188294 0.364633,0.124533 C0.349689,0.029888 0.292902,0 0.24807,0 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(-3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.608332)">+            <g transform="translate(-0.253051, -0.331756)">+              <path d="M0.292902,0.637609 C0.292902,0.661519 0.292902,0.663512 0.269988,0.663512 C0.208219,0.599751 0.120548,0.599751 0.088667,0.599751 L0.088667,0.568867 C0.108593,0.568867 0.167372,0.568867 0.219178,0.59477 L0.219178,0.078705 C0.219178,0.042839 0.216189,0.030884 0.126526,0.030884 L0.094645,0.030884 L0.094645,0 C0.129514,0.002989 0.216189,0.002989 0.25604,0.002989 C0.295891,0.002989 0.382565,0.002989 0.417435,0 L0.417435,0.030884 L0.385554,0.030884 C0.29589,0.030884 0.292902,0.041843 0.292902,0.078705 L0.292902,0.637609 Z" />+            </g>+          </g>+        </g>+      </g>+      <g transform="translate(3.117691, -1.8)">+        <g>+          <circle stroke="#000000" fill="#FFFFFF" fill-opacity="1" r="0.3" />+          <g transform="scale(0.503132)">+            <g transform="translate(-0.248568, -0.331756)">+              <path d="M0.126526,0.076712 L0.23213,0.179328 C0.387547,0.316812 0.447323,0.37061 0.447323,0.470237 C0.447323,0.583811 0.357659,0.663512 0.236115,0.663512 C0.123537,0.663512 0.049813,0.571856 0.049813,0.483188 C0.049813,0.427397 0.099626,0.427397 0.102615,0.427397 C0.119552,0.427397 0.154421,0.439352 0.154421,0.480199 C0.154421,0.506102 0.136488,0.532005 0.101619,0.532005 C0.093649,0.532005 0.091656,0.532005 0.088667,0.531009 C0.111582,0.595766 0.16538,0.632628 0.223163,0.632628 C0.313823,0.632628 0.356663,0.55193 0.356663,0.470237 C0.356663,0.390535 0.306849,0.311831 0.252055,0.250062 L0.060772,0.036862 C0.049813,0.025903 0.049813,0.02391 0.049813,0 L0.419427,0 L0.447323,0.17335 L0.422416,0.17335 C0.417435,0.143462 0.410461,0.099626 0.400498,0.084682 C0.393524,0.076712 0.327771,0.076712 0.305853,0.076712 L0.126526,0.076712 Z" />+            </g>+          </g>+        </g>+      </g>+    </g>+  </g>+</svg></g></g></svg>
doctests.hs view
@@ -31,7 +31,6 @@           , "DeriveFunctor"           , "DeriveFoldable"           , "DeriveTraversable"-          , "AutoDeriveTypeable"           , "DeriveGeneric"           , "FlexibleInstances"           , "FlexibleContexts"@@ -55,12 +54,22 @@ modules =   [ "Data.Range"   , "Data.CircularList.Util"+  , "Data.Vector.Circular.Util"   , "Data.Permutation"   , "Data.CircularSeq"   , "Data.LSeq"   , "Data.PlanarGraph"   , "Data.PlanarGraph.Dart"   , "Data.PlanarGraph.Core"+  , "Data.PlanarGraph.Mutable"+  , "Data.PlanarGraph.Immutable"   , "Data.Tree.Util"   , "Data.Set.Util"++  , "Data.List.Util"+  , "Data.List.Alternating"+  , "Data.List.Zipper"++  , "Data.Double.Approximate"+  , "Data.Double.Shaman"   ]
hgeometry-combinatorial.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                hgeometry-combinatorial-version:             0.10.0.0+version:             0.14 synopsis:            Data structures, and Data types. description:     The Non-geometric data types and algorithms used in HGeometry.@@ -13,7 +13,7 @@ maintainer:          frank@fstaals.net -- copyright: -tested-with:         GHC >= 8.4+tested-with:         GHC >= 8.8  category:            Geometry build-type:          Simple@@ -24,10 +24,13 @@                      -- examples/**/*.out  extra-source-files:  README.md+                     changelog                      changelog.org  Extra-doc-files:     docs/Data/PlanarGraph/testG.png                      docs/Data/PlaneGraph/planegraph.png+                     docs/Data/PlanarGraph/*.svg+                     docs/Data/PlanarGraph/*.compact.svg                      -- docs/**/*.png  cabal-version:       2.0@@ -42,60 +45,98 @@   exposed-modules:                     -- * Algorithmic Strategies                     Algorithms.DivideAndConquer+                    Algorithms.BinarySearch+                    Algorithms.LogarithmicMethod                      -- * Graph Algorithms                     Algorithms.Graph.DFS+                    Algorithms.Graph.BFS                     Algorithms.Graph.MST+                    Algorithms.FloydWarshall                       Algorithms.StringSearch.KMP ++++                    -- * Numeric Data Types+                    Data.RealNumber.Rational+                    Data.Double.Approximate+                    Data.Double.Shaman++                    -- * Measurements+                    Data.Measured+                    Data.Measured.Class+                    Data.Measured.Size+                     -- * General Data Types                     Data.UnBounded                     Data.Intersection                     Data.Range+                     Data.Ext+                    -- Data.Ext.Multi+                     Data.LSeq                     Data.CircularSeq                     Data.Sequence.Util                     Data.BinaryTree-                    Data.BinaryTree.Zipper                      Data.CircularList.Util-                    Data.BalBST+                    Data.Vector.Circular.Util                     Data.OrdSeq-                    Data.SlowSeq                     Data.Tree.Util                     Data.Util +                    Data.IndexedDoublyLinkedList+                    -- Data.IndexedDoublyLinkedList.Unboxed+                    Data.IndexedDoublyLinkedList.Bare+                     Data.DynamicOrd+                     Data.Set.Util +                    Data.List.Set+                    Data.List.Util+                    Data.List.Zipper+                    Data.List.Alternating+                     -- * Planar Graphs                     Data.Permutation                     Data.PlanarGraph+                    Data.PlanarGraph.Persistent+                    Data.PlanarGraph.Mutable+                    Data.PlanarGraph.Immutable                     Data.PlanarGraph.AdjRep                     Data.PlanarGraph.IO-                    Data.PlanarGraph.Dart-                    Data.PlanarGraph.Core-                    Data.PlanarGraph.Dual                     Data.PlanarGraph.EdgeOracle+                    Data.PlanarGraph.Dart                      -- * Other                     System.Random.Shuffle+                     Control.Monad.State.Persistent++                    Control.CanAquire+                     Data.Yaml.Util -  other-modules:+  other-modules:    Data.PlanarGraph.Internal+                    Data.PlanarGraph.Core+                    Data.PlanarGraph.Dual +   -- other-extensions:   build-depends:                 base                    >= 4.11      &&     < 5+              , array                   >= 0.4               , bifunctors              >= 4.1               , bytestring              >= 0.10               , containers              >= 0.5.9+              -- , data-default               , dlist                   >= 0.7-              , lens                    >= 4.2+              , lens                    >= 4.18               , contravariant           >= 1.5               , semigroupoids           >= 5               , semigroups              >= 0.18@@ -103,17 +144,26 @@               , deepseq                 >= 1.1               , fingertree              >= 0.1               , MonadRandom             >= 0.5+              , random                  >= 1.1               , QuickCheck              >= 2.5               , quickcheck-instances    >= 0.3               , reflection              >= 2.1+              , primitive               >= 0.6.3.0+              , linear                  >= 1.21+              , hashable                >= 1.2+              , witherable              >= 0.4                , vector                  >= 0.11               , data-clist              >= 0.1.2.3+              , vector-circular         >= 0.1.4+              , nonempty-vector         >= 0.2.0.0               , vector-builder          >= 0.3.7+              , unordered-containers                , aeson                   >= 1.0               , yaml                    >= 0.8               , text                    >= 1.1.1.0+              , math-functions                , mtl               , template-haskell@@ -153,6 +203,9 @@                     , FlexibleContexts                     , MultiParamTypeClasses +  c-sources: cbits/erf.c+  extra-libraries: m+ test-suite doctests   type:          exitcode-stdio-1.0   ghc-options:   -threaded@@ -176,11 +229,16 @@    other-modules: Algorithms.StringSearch.KMPSpec                  Algorithms.DivideAndConquerSpec+                 Algorithms.LogarithmicMethodSpec+                 Algorithms.Graph.DFSSpec+                 Algorithms.Graph.BFSSpec                  Data.RangeSpec                  Data.EdgeOracleSpec                  Data.PlanarGraphSpec                  Data.OrdSeqSpec                  Data.CircularSeqSpec+                 Data.IndexedDoublyLinkedListSpec+                 Data.RealNumber.RationalSpec     build-depends:        base@@ -189,6 +247,7 @@                       , quickcheck-instances    >= 0.3                       , approximate-equality    >= 1.1.0.2                       , hgeometry-combinatorial+                      , deepseq                       , lens                       , data-clist                       , linear@@ -198,11 +257,17 @@                       , vector                       , containers                       , random-                      , singletons                       , filepath                       , directory                       , yaml                       , MonadRandom+                      , semigroupoids+  -- -- Such a mess:+  -- if impl(ghc == 9.*)+  --   build-depends:      singletons              == 3.*+  --                     , singletons-th           == 3.*+  -- else+  --   build-depends:      singletons              == 2.*    default-extensions: TypeFamilies                     , GADTs@@ -227,8 +292,6 @@                     , DeriveFunctor                     , DeriveFoldable                     , DeriveTraversable--                    , AutoDeriveTypeable                      , FlexibleInstances                     , FlexibleContexts
+ src/Algorithms/BinarySearch.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE UndecidableInstances #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.BinarySearch+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Algorithms.BinarySearch where++import           Control.Applicative ((<|>))+import           Data.Kind+import           Data.Sequence (Seq, ViewL(..),ViewR(..))+import qualified Data.Sequence as Seq+import           Data.Set (Set)+import qualified Data.Set.Internal as Set+import qualified Data.Vector.Generic as V+--------------------------------------------------------------------------------++-- | Given a monotonic predicate p, a lower bound l, and an upper bound u, with:+--  p l = False+--  p u = True+--  l < u.+--+-- Get the index h such that everything strictly smaller than h has: p i =+-- False, and all i >= h, we have p h = True+--+-- running time: \(O(\log(u - l))\)+{-# SPECIALIZE binarySearch :: (Int -> Bool) -> Int -> Int -> Int #-}+{-# SPECIALIZE binarySearch :: (Word -> Bool) -> Word -> Word -> Word #-}+binarySearch   :: Integral a => (a -> Bool) -> a -> a -> a+binarySearch p = go+  where+    go l u = let d = u - l+                 m = l + (d `div` 2)+             in if d == 1 then u else if p m then go l m+                                             else go m u++-- | Given a value \(\varepsilon\), a monotone predicate \(p\), and two values \(l\) and+-- \(u\) with:+--+-- - \(p l\) = False+-- - \(p u\) = True+-- - \(l < u\)+--+-- we find a value \(h\) such that:+--+-- - \(p h\) = True+-- - \(p (h - \varepsilon)\) = False+--+-- >>> binarySearchUntil (0.1) (>= 0.5) 0 (1 :: Double)+-- 0.5+-- >>> binarySearchUntil (0.1) (>= 0.51) 0 (1 :: Double)+-- 0.5625+-- >>> binarySearchUntil (0.01) (>= 0.51) 0 (1 :: Double)+-- 0.515625+binarySearchUntil       :: (Fractional r, Ord r)+                        => r+                        -> (r -> Bool) -> r -> r -> r+binarySearchUntil eps p = go+  where+    go l u | u - l < eps = u+           | otherwise   = let m = (l + u) / 2+                           in if p m then go l m else go m u+++--------------------------------------------------------------------------------+-- * Binary Searching in some data structure+++class BinarySearch v where+  type Index v :: Type+  type Elem  v :: Type++  -- | Given a monotonic predicate p and a data structure v, find the+  -- element v[h] such that that+  --+  -- for every index i <  h we have p v[i] = False, and+  -- for every inedx i >= h we have p v[i] = True+  --+  -- returns Nothing if no element satisfies p+  --+  -- running time: \(O(T*\log n)\), where \(T\) is the time to execute the+  -- predicate.+  binarySearchIn     :: (Elem v -> Bool) -> v -> Maybe (Elem v)++  -- | Given a monotonic predicate p and a data structure v, find the+  -- index h such that that+  --+  -- for every index i <  h we have p v[i] = False, and+  -- for every inedx i >= h we have p v[i] = True+  --+  -- returns Nothing if no element satisfies p+  --+  -- running time: \(O(T*\log n)\), where \(T\) is the time to execute the+  -- predicate.+  binarySearchIdxIn :: (Elem v -> Bool) -> v -> Maybe (Index v)++--------------------------------------------------------------------------------+-- * Searching on a Sequence++instance BinarySearch (Seq a) where+  type Index (Seq a) = Int+  type Elem  (Seq a) = a++  -- ^ runs in \(O(T*\log^2 n)\) time.+  binarySearchIn p s = Seq.index s <$>  binarySearchIdxIn p s++  -- ^ runs in \(O(T*\log^2 n)\) time.+  binarySearchIdxIn p s = case Seq.viewr s of+                            EmptyR                 -> Nothing+                            (_ :> x)   | p x       -> Just $ case Seq.viewl s of+                              (y :< _) | p y          -> 0+                              _                       -> binarySearch p' 0 u+                                       | otherwise -> Nothing+    where+      p' = p . Seq.index s+      u  = Seq.length s - 1++instance {-# OVERLAPPABLE #-} V.Vector v a => BinarySearch (v a) where+  type Index (v a) = Int+  type Elem  (v a) = a++  binarySearchIdxIn p' v | V.null v   = Nothing+                         | not $ p n' = Nothing+                         | otherwise  = Just $ if p 0 then 0 else binarySearch p 0 n'+    where+      n' = V.length v - 1+      p = p' . (v V.!)++  binarySearchIn p v = (v V.!) <$>  binarySearchIdxIn p v++instance BinarySearch (Set a) where+  type Index (Set a) = Int+  type Elem  (Set a) = a++  binarySearchIn p = go+    where+      go = \case+        Set.Tip                     -> Nothing+        Set.Bin _ k l r | p k       -> go l <|> Just k+                        | otherwise -> go r++  binarySearchIdxIn p = go+    where+      go = \case+        Set.Tip                     -> Nothing+        Set.Bin _ k l r | p k       -> go l <|> Just (Set.size l)+                        | otherwise -> (+ (1 + Set.size l)) <$> go r
src/Algorithms/DivideAndConquer.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.DivideAndConquer+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Algorithms.DivideAndConquer( divideAndConquer                                   , divideAndConquer1                                   , divideAndConquer1With@@ -7,59 +14,68 @@                                   , mergeSortedListsBy                                   ) where +import qualified Data.Foldable as F import           Data.List.NonEmpty (NonEmpty(..),(<|)) import qualified Data.List.NonEmpty as NonEmpty-+import           Data.Semigroup.Foldable  -- | Divide and conquer strategy ----- the running time is: O(n*L) + T(n) = 2T(n/2) + M(n)+-- the running time satifies T(n) = 2T(n/2) + M(n), ----- where M(n) is the time corresponding to the semigroup operation of s+-- where M(n) is the time corresponding to the semigroup operation of s on n elements. ---divideAndConquer1 :: Semigroup s => (a -> s) -> NonEmpty a -> s+--+divideAndConquer1 :: (Foldable1 f, Semigroup s) => (a -> s) -> f a -> s divideAndConquer1 = divideAndConquer1With (<>) ---- | Divide and conquer for-divideAndConquer   :: Monoid s => (a -> s) -> [a] -> s-divideAndConquer g = maybe mempty (divideAndConquer1 g) . NonEmpty.nonEmpty+-- | Divide and conquer strategy. See 'divideAndConquer1'.+divideAndConquer   :: (Foldable f, Monoid s) => (a -> s) -> f a -> s+divideAndConquer g = maybe mempty (divideAndConquer1 g) . NonEmpty.nonEmpty . F.toList +{- HLINT ignore divideAndConquer1With -} -- | Divide and conquer strategy ----- the running time is: O(n*L) + T(n) = 2T(n/2) + M(n)+-- the running time satifies T(n) = 2T(n/2) + M(n), ----- where M(n) is the time corresponding to the merge operation s+-- where M(n) is the time corresponding to the semigroup operation of s on n elements. ---divideAndConquer1With         :: (s -> s -> s) -> (a -> s) -> NonEmpty a -> s-divideAndConquer1With (<.>) g = repeatedly merge . fmap g+divideAndConquer1With         :: Foldable1 f => (s -> s -> s) -> (a -> s) -> f a -> s+divideAndConquer1With (<.>) g = repeatedly merge . fmap g . toNonEmpty   where     repeatedly _ (t :| []) = t     repeatedly f ts        = repeatedly f $ f ts      merge ts@(_ :| [])  = ts     merge (l :| r : []) = l <.> r :| []-    merge (l :| r : ts) = l <.> r <| (merge $ NonEmpty.fromList ts)+    merge (l :| r : ts) = l <.> r <| merge (NonEmpty.fromList ts)   -------------------------------------------------------------------------------- -- * Merging NonEmpties/Sorted lists +-- | Merges two sorted non-Empty lists in linear time. mergeSorted :: Ord a => NonEmpty a -> NonEmpty a -> NonEmpty a mergeSorted = mergeSortedBy compare +-- | Merges two sorted lists in linear time. mergeSortedLists :: Ord a => [a] -> [a] -> [a] mergeSortedLists = mergeSortedListsBy compare  -- | Given an ordering and two nonempty sequences ordered according to that--- ordering, merge them+-- ordering, merge them.+--+-- running time: \(O(n*T)\), where \(n\) is the length of the list,+-- and \(T\) the time required to compare two elements. mergeSortedBy           :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a -> NonEmpty a mergeSortedBy cmp ls rs = NonEmpty.fromList                         $ mergeSortedListsBy cmp (NonEmpty.toList ls) (NonEmpty.toList rs) - -- | Given an ordering and two nonempty sequences ordered according to that -- ordering, merge them+--+-- running time: \(O(n*T)\), where \(n\) is the length of the list,+-- and \(T\) the time required to compare two elements. mergeSortedListsBy     :: (a -> a -> Ordering) -> [a] -> [a] -> [a] mergeSortedListsBy cmp = go   where
+ src/Algorithms/FloydWarshall.hs view
@@ -0,0 +1,56 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Geometry.Polygon.Core+-- Copyright   :  (C) David Himmelstrup+-- License     :  see the LICENSE file+-- Maintainer  :  David Himmelstrup+--+-- Implementation of Floyd-Warshall shortest path algorithm.+--+-- See Wikipedia article for details: https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm+--+--------------------------------------------------------------------------------+module Algorithms.FloydWarshall+  ( mkIndex+  , mkGraph+  , floydWarshall+  ) where++import           Control.Monad               (forM_, when)+import           Control.Monad.ST            (ST)+import           Data.Vector.Unboxed.Mutable as V (MVector, length, replicate, unsafeRead,+                                                   unsafeWrite, Unbox)++-- | \( O(n^3) \)+floydWarshall :: (Unbox a, Fractional a, Ord a) => Int -> MVector s (a, Int) -> ST s ()+floydWarshall n graph = do+    let nSq = V.length graph+    when (n*n /= nSq) $ error "Bad bounds"+    forM_ [0 .. n-1] $ \k ->+      forM_ [0 .. n-1] $ \i ->+        forM_ [0 .. n-1] $ \j -> do+          (distIJ, _) <- access (i,j)+          (distIK, pathIK) <- access (i,k)+          (distKJ, _) <- access (k,j)+          let indirectDist = distIK + distKJ+          when (distIJ > indirectDist+indirectDist*eps && distIJ > distIK && distIJ > distKJ) $+            put (i,j) (indirectDist, pathIK)+  where+    access idx = V.unsafeRead graph (mkIndex n idx)+    put idx e = V.unsafeWrite graph (mkIndex n idx) e+    eps = 1e-10 -- When two paths are nearly the same length, pick the one with the fewest segments.++-- | Compute the index of an element in a given range.+mkIndex :: Num a => a -> (a, a) -> a+mkIndex n (i,j) = i*n+j++-- | Construct a weighted graph from \(n\) vertices, a max bound, and a list of weighted edges.+mkGraph :: (Unbox a, Num a) => Int -> a -> [(Int,Int,a)] -> ST s (MVector s (a, Int))+mkGraph n maxValue edges = do+  graph <- V.replicate (n*n) (maxValue, maxBound)+  forM_ [0..n-1] $ \v -> do+    unsafeWrite graph (mkIndex n (v,v)) (0, v)+  forM_ edges $ \(i,j,cost) -> do+    unsafeWrite graph (mkIndex n (i,j)) (cost, j)+    unsafeWrite graph (mkIndex n (j,i)) (cost, i)+  return graph
+ src/Algorithms/Graph/BFS.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.Graph.BFS+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Algorithms.Graph.BFS+  ( bfs+  , bfs'+  ) where++import           Control.Monad.ST.Strict+import qualified Data.Foldable as F+import           Data.Sequence (Seq(..))+import qualified Data.Sequence as Seq+import           Data.Tree+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV+import qualified Data.Vector.Unboxed.Mutable as UMV+import           Witherable++--------------------------------------------------------------------------------++-- | Runs a BFS from the first vertex in the graph. The graph is given+-- in adjacency list representation.+--+-- running time: \(O(V + E)\)+bfs      :: Foldable f => Int -> V.Vector (v, f Int) -> Tree v+bfs s gr = fmap (fst . (gr V.!)) . bfs' s . fmap snd $ gr++-- | Runs a BFS from the first vertex in the graph. The graph is given+-- in adjacency list representation.+--+-- running time: \(O(V + E)\)+bfs'      :: Foldable f => Int -> V.Vector (f Int) -> Tree Int+bfs' s gr = extract s $ V.create+         $ do st  <- UMV.replicate n False+              out <- MV.new n+              go0 st out (s :<| mempty)+              pure out+  where+    n = V.length gr+    go0        :: forall s. UMV.MVector s Bool -> MV.MVector s [Int]+               -> Seq Int -> ST s ()+    go0 st out = go+      where+        visit i = do b <- UMV.read st i+                     UMV.write st i True -- mark i as visited+                     pure $ if b then Nothing else Just i++        go :: Seq Int -> ST s ()+        go = \case+          Empty       -> pure ()+          (u:<|queue) -> do ns <- wither visit . F.toList $ gr V.! u+                            MV.write out u ns -- write that u's children are ns+                            go (queue <> Seq.fromList ns)+++-- | Give na root index and a vector s.t. v[i] lists the children of+-- node i, builds the acutal tree.+extract     :: Int -> V.Vector [Int] -> Tree Int+extract s v = go s+  where+    go i = Node i (map go $ v V.! i)
src/Algorithms/Graph/DFS.hs view
@@ -1,14 +1,21 @@ {-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.Graph.DFS+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Algorithms.Graph.DFS where -import           Control.Monad.ST (ST,runST)+import           Control.Monad.ST            (ST, runST) import           Data.Maybe import           Data.PlanarGraph import           Data.Tree-import qualified Data.Vector as V-import qualified Data.Vector.Generic as GV+import qualified Data.Vector                 as V+import qualified Data.Vector.Generic         as GV import qualified Data.Vector.Unboxed.Mutable as UMV-+import qualified Data.IntSet as IntSet  -- | DFS on a planar graph. --@@ -51,3 +58,20 @@                    False -> do                               visit bv u                               Just . Node u . catMaybes <$> mapM (dfs'' bv) (neighs u)++-- | DFS, from a given vertex, on a graph in AdjacencyLists representation. Cycles are not removed.+-- If your graph may contain cycles, see 'dfsFilterCycles'.+--+-- Running time: \(O(k)\), where \(k\) is the number of nodes consumed.+dfsSensitive :: forall s w. (VertexId s w -> [VertexId s w]) -> VertexId s w -> Tree (VertexId s w)+dfsSensitive neighs u = Node u $ map (dfsSensitive neighs) (neighs u)++-- | Remove infinite cycles from a DFS search tree.+dfsFilterCycles :: Tree (VertexId s w) -> Tree (VertexId s w)+dfsFilterCycles = worker IntSet.empty+  where+    worker seen (Node root forest) = Node root+      [ Node (VertexId v) (map (worker (IntSet.insert v seen)) sub)+      | Node (VertexId v) sub <- forest+      , v `IntSet.notMember` seen+      ]
src/Algorithms/Graph/MST.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.Graph.MST+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Algorithms.Graph.MST( mst                            , mstEdges                            , makeTree
+ src/Algorithms/LogarithmicMethod.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE DefaultSignatures #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.LogarithmicMethod+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Algorithms.LogarithmicMethod+  ( InsertionOnly(..)+  , empty+  , LogarithmicMethodDS(..)+  , insert+  , queryWith+  )+  where++import Data.List.NonEmpty (NonEmpty(..))+import Data.Maybe (mapMaybe)+import Data.Semigroup.Foldable++--------------------------------------------------------------------------------++-- | Represents an insertion-only data structure built from static+-- data structures.+--+-- In particular, we maintain \(O(\log n)\) static data structures of+-- sizes \(2^i\), for \(i \in [0..c\log n]\).+newtype InsertionOnly static a = InsertionOnly [Maybe (static a)]+  deriving (Show,Eq,Ord)++-- | Builds an empty structure+empty :: InsertionOnly static a+empty = InsertionOnly []++instance Functor static => Functor (InsertionOnly static) where+  fmap f (InsertionOnly dss) = InsertionOnly $ map (fmap (fmap f)) dss++instance Traversable static => Traversable (InsertionOnly static) where+  traverse f (InsertionOnly dss) = InsertionOnly <$> traverse (traverse (traverse f)) dss++instance Foldable static => Foldable (InsertionOnly static) where+  foldMap f = queryWith (foldMap f)+  length = sum . mapMaybe (uncurry (<$)) . withSizes++instance LogarithmicMethodDS static a => Semigroup (InsertionOnly static a) where+  (InsertionOnly ds1) <> (InsertionOnly ds2) = InsertionOnly $ runMergeWith Nothing ds1 0 ds2 0++instance LogarithmicMethodDS static a => Monoid (InsertionOnly static a) where+  mempty = empty+++class LogarithmicMethodDS static a where+  {-# MINIMAL build #-}+  -- | Create a new static data structure storing only one value.+  singleton :: a          -> static a+  singleton = build . (:| [])++  -- | Given a NonEmpty list of a's build a static a.+  build     :: NonEmpty a -> static a++  -- | Merges two structurs of the same size. Has a default+  -- implementation via build in case the static structure is Foldable1.+  merge     :: static a   -> static a -> static a+  default merge :: Foldable1 static => static a -> static a -> static a+  merge as bs = build $ toNonEmpty as <> toNonEmpty bs+++type Power = Word++-- | 2^h, for whatever value h.+pow2   :: Integral i => Power -> i+pow2 h = 2 ^ h++-- | Annotate the data structures with their sizes+withSizes                     :: Integral i => InsertionOnly static a -> [(i,Maybe (static a))]+withSizes (InsertionOnly dss) = zipWith (\i ds -> (pow2 i,ds))  [0..] dss++-- | Inserts an element into the data structure+--+-- running time: \(O(M(n)\log n / n)\), where \(M(n)\) is the time+-- required to merge two data structures of size \(n\).+insert                       :: LogarithmicMethodDS static a+                             => a -> InsertionOnly static a -> InsertionOnly static a+insert x (InsertionOnly dss) = InsertionOnly $ runMerge (singleton x) 0 0 dss++-- | Runs the merging procedure. If there are two data structures of+-- the same size they are merged.+runMerge         :: LogarithmicMethodDS static a+                 => static a -- ^ ds1+                 -> Power    -- ^ ds1 has size 2^i+                 -> Power    -- ^ the first entry in the next list corresponds to size 2^j+                 -> [Maybe (static a)] -> [Maybe (static a)]+runMerge ds1 i j = \case+  []                                -> [Just ds1]+  dss@(Nothing  : dss') | i == j    -> Just ds1 : dss' -- replace+                        | otherwise -> Just ds1 : dss  -- cons+  dss@(Just ds2 : dss') | i == j    -> Nothing : runMerge (ds1 `merge` ds2) (i+1) (j+1) dss'+                        | otherwise -> Just ds1 : dss -- cons -- I don't think insert can ever+                                                              -- trigger this scenario.++-- | merges two structures (potentially with a carry)+--+-- invariant: size carry == size ds1 <= size ds2+runMergeWith                ::  LogarithmicMethodDS static a+                            => Maybe (static a) -- ^ carry, if it exists+                            -> [Maybe (static a)] -> Power+                            -- ^ size of the first ds+                            -> [Maybe (static a)] -> Power+                            -- ^ size of the second ds+                            -> [Maybe (static a)]+runMergeWith mc ds1 i ds2 j = case (ds1,ds2) of+  ([],_)            -> case mc of+                         Nothing  -> ds2+                         Just c   -> runMerge c i j ds2+  (_,[])            -> case mc of+                         Nothing  -> ds1+                         Just c   -> runMerge c i i ds1+  (m1:ds1',m2:ds2') -> case (m1,m2) of+    (Nothing,Nothing) -> mc : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+    (Nothing,Just d2) -> case mc of+         Nothing | i == j    -> m2 : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+                 | otherwise -> m1 : runMergeWith Nothing ds1' (i+1) ds2 j+         Just c  | i == j    -> Nothing : runMergeWith (Just $ c `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> mc : runMergeWith Nothing ds1' (i+1) ds2 j+                   -- i < j, so invariant (i+1) <= j again holds holds++    (Just d1,Nothing) -> case mc of+                           Nothing -> m1 : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+                           Just c  -> Nothing : runMergeWith (Just $ c `merge` d1) ds1' (i+1) ds2' (j+1)++    (Just d1,Just d2) -> case mc of+         Nothing | i == j    -> Nothing : runMergeWith (Just $ d1 `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> m1      : runMergeWith Nothing ds1' (i+1) ds2 j++         Just c  | i == j    -> mc : runMergeWith (Just $ d1 `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> Nothing : runMergeWith (Just $ c `merge` d1) ds1' (i+1) ds2 j+                       -- i < j, so invariant holds++-- | Given a decomposable query algorithm for the static structure,+-- lift it to a query algorithm on the insertion only structure.+--+-- pre: (As indicated by the Monoid constraint), the query answer+-- should be decomposable. I.e. we should be able to anser the query+-- on a set \(A \cup B\) by answering the query on \(A\) and \(B\)+-- separately, and combining their results.+--+-- running time: \(O(Q(n)\log n)\), where \(Q(n)\) is the query time+-- on the static structure.+queryWith                           :: Monoid m => (static a -> m) -> InsertionOnly static a -> m+queryWith query (InsertionOnly dss) = foldMap (foldMap query) dss
+ src/Control/CanAquire.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE FunctionalDependencies #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Control.CanAquire+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Control.CanAquire(+      runAcquire+    , CanAquire(..)+    , HasIndex(..)++    , replaceByIndex, labelWithIndex+    , I+    ) where++import           Control.Monad.ST.Strict+import           Control.Monad.State.Strict+import           Data.Reflection+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV+import Unsafe.Coerce(unsafeCoerce)++--------------------------------------------------------------------------------++-- | Run a computation on something that can aquire i's.+runAcquire         :: forall t a b. Traversable t+                   => (forall s. CanAquire (I s a) a => t (I s a) -> b)+                   -> t a -> b+runAcquire alg pts = reify v $ \px -> alg (coerceTS px ts)+  where+    (v,ts) = replaceByIndex pts++    coerceTS   :: proxy s -> t Int -> t (I s a)+    coerceTS _ = unsafeCoerce -- fmap I+      -- Ideally this would just be a coerce. But GHC doesn't want to do that.++class HasIndex i Int => CanAquire i a where+  -- | A value of type i can obtain something of type @\'a\'@+  aquire  :: i -> a++class HasIndex t i | t -> i where+  -- | Types that have an instance of this class can act as indices.+  indexOf :: t -> i++--------------------------------------------------------------------------------++-- | Replaces every element by an index. Returns the new traversable+-- containing only these indices, as well as a vector with the+-- values. (such that indexing in this value gives the original+-- value).+replaceByIndex     :: forall t a. Traversable t => t a -> (V.Vector a, t Int)+replaceByIndex ts' = runST $ do+                               v <- MV.new n+                               t <- traverse (lbl v) ts+                               (,t) <$> V.unsafeFreeze v+  where+    (ts, n) = labelWithIndex ts'++    lbl         :: MV.MVector s' a -> (Int,a) -> ST s' Int+    lbl v (i,x) = MV.write v i x >> pure i++-- | Label each element with its index. Returns the new collection as+-- well as its size.+labelWithIndex :: Traversable t => t a -> (t (Int, a), Int)+labelWithIndex = flip runState 0 . traverse lbl+  where+    lbl   :: a -> State Int (Int,a)+    lbl x = do i <- get+               put $ i+1+               pure (i,x)+++--------------------------------------------------------------------------------++-- | A type that can act as an Index.+newtype I (s :: *) a = I Int deriving (Eq, Ord, Enum)++instance Show (I s a) where+  showsPrec i (I j) = showsPrec i j++instance HasIndex (I s a) Int where+  indexOf (I i) = i++instance Reifies s (V.Vector a) => I s a `CanAquire` a where+  aquire (I i) = let v = reflect @s undefined in v V.! i
src/Control/Monad/State/Persistent.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Control.Monad.State.Persistent+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Control.Monad.State.Persistent( PersistentStateT                                      , PersistentState                                      , store@@ -32,7 +39,7 @@               put (s' :| os)               return x --- | run a persistentStateT, returns a triplet with the value, the last state+-- | Run a persistentStateT, returns a triplet with the value, the last state -- and a list of all states (including the last one) in chronological order runPersistentStateT :: Functor m => PersistentStateT s m a -> s -> m (a,s,[s]) runPersistentStateT (PersistentStateT act) initS = f <$> runStateT act (initS :| [])@@ -42,7 +49,10 @@  -------------------------------------------------------------------------------- +-- | A State monad that can store earlier versions of the state. type PersistentState s = PersistentStateT s Identity +-- | Run a persistentStateT, returns a triplet with the value, the last state+-- and a list of all states (including the last one) in chronological order runPersistentState     :: PersistentState s a -> s -> (a,s,[s]) runPersistentState act = runIdentity . runPersistentStateT act
− src/Data/BalBST.hs
@@ -1,378 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-module Data.BalBST where--import           Control.Applicative((<|>))-import           Data.Bifunctor-import           Data.Function (on)-import           Data.Functor.Contravariant-import qualified Data.List as L-import           Data.Maybe-import qualified Data.Tree as T-import           Prelude hiding (lookup,null)-------------------------------------------------------------------------------------- | Describes how to search in a tree-data TreeNavigator k a = Nav { goLeft     :: a -> k -> Bool-                             , extractKey :: a -> a -> k-                             }--instance Contravariant (TreeNavigator k) where-  contramap f (Nav gL eK) = Nav (\a k -> gL (f a) k) (\x y -> eK (f x) (f y))---ordNav :: Ord a => TreeNavigator a a-ordNav = Nav (<=) min---ordNavBy   :: Ord b => (a -> b) ->  TreeNavigator b a-ordNavBy f = Nav (\x k -> f x <= k) (min `on` f)----- instance Functor (TreeNavigator k) where---   fmap f Nav{..} = Nav (\b k -> )------ | A balanced binary search tree-data BalBST k a = BalBST { nav    :: !(TreeNavigator k a)-                         , toTree :: !(Tree k a)-                         }--instance (Show k, Show a) => Show (BalBST k a) where-  show (BalBST _ t) = "BalBST (" ++ show t ++ ")"---data Color = Red | Black deriving (Show,Read,Eq,Ord)--type Height = Int---- Red-Black tree with values in the leaves-data Tree k a = Empty-              | Leaf !a-              | Node !Color !Height (Tree k a) !k (Tree k a) deriving (Show,Eq)-------------------------------------------------------------------------------------- | Creates an empty BST-empty   :: TreeNavigator k a -> BalBST k a-empty n = BalBST n Empty----- | \(O(n\log n)\)-fromList :: TreeNavigator k a -> [a] -> BalBST k a-fromList n = foldr insert (empty n)--fromList' :: Ord a => [a] -> BalBST a a-fromList' = fromList ordNav----- -- | \(O(n)\)--- fromAscList :: TreeNavigator k a -> [a] -> BalBST k a--- fromAscList = undefined--------------------------------------------------------------------------------------- | Check if the tree is empty-null                  :: BalBST k a -> Bool-null (BalBST _ Empty) = True-null _                = False---- | Test if an element occurs in the BST.--- \(O(\log n)\)-lookup :: Eq a => a -> BalBST k a -> Maybe a-lookup x (BalBST Nav{..} t) = lookup' t-  where-    lookup' Empty            = Nothing-    lookup' (Leaf y)         = if x == y then Just y else Nothing-    lookup' (Node _ _ l k r)-      | goLeft x k           = lookup' l-      | otherwise            = lookup' r---- | \(O(\log n)\)-member   :: Eq a => a -> BalBST k a -> Bool-member x = isJust . lookup x---- | Search for the Predecessor--- \(O(\log n)\)-lookupLE :: Ord k => k -> BalBST k a -> Maybe a-lookupLE kx (BalBST n@Nav{..} t) = lookup' t-  where-    lookup' Empty            = Nothing-    lookup' (Leaf y)         = if goLeft y kx then Just y else Nothing-    lookup' (Node _ _ l k r)-      | kx <= k              = lookup' l-      | otherwise            = lookup' r <|> lookupMax (BalBST n l)----- | Insert an element in the BST.------ \(O(\log n)\)-insert :: a -> BalBST k a -> BalBST k a-insert x (BalBST n@Nav{..} t) = BalBST n (blacken $ insert' t)-  where-    insert' Empty    = Leaf x-    insert' (Leaf y) = let k     = extractKey x y-                           (l,r) = if goLeft x k then (x,y) else (y,x)-                       in red 2 (Leaf l) k (Leaf r)-    insert' (Node c h l k r)-      | goLeft  x k  = balance c h (insert' l) k r-      | otherwise    = balance c h l           k (insert' r)------ delete = undefined---- | Delete (one occurance of) an element.--- \(O(\log n)\)-delete                        :: Eq a => a -> BalBST k a -> BalBST k a-delete x t = let Split l _ r = split x t-                 n           = nav t-             in BalBST n $ joinWith n l r----- (BalBST n@Nav{..} t) = delete' t---   where---     delete' Empty      = Empty---     delete' l@(Leaf y) = if x == y then Empty else l---     delete' (Node c h l k r)---       | goLeft x k     =---------------------------------------------------------------------------------------- | Extract the minimum from the tree--- \(O(\log n)\)-minView              :: BalBST k a -> Maybe (a, Tree k a)-minView (BalBST n t) = minView' t-  where-    minView' Empty            = Nothing-    minView' (Leaf x)         = Just (x,Empty)-    minView' (Node _ _ l _ r) = fmap (flip (joinWith n) r) <$> minView' l--lookupMin :: BalBST k b -> Maybe b-lookupMin = fmap fst . maxView---- | Extract the maximum from the tree--- \(O(\log n)\)-maxView              :: BalBST k a -> Maybe (a, Tree k a)-maxView (BalBST n t) = maxView' t-  where-    maxView' Empty            = Nothing-    maxView' (Leaf x)         = Just (x,Empty)-    maxView' (Node _ _ l _ r) = fmap (joinWith n l) <$> maxView' r--lookupMax :: BalBST k b -> Maybe b-lookupMax = fmap fst . maxView----- | Joins two BSTs. Assumes that the ranges are disjoint. It takes the left Tree nav------ \(O(\log n)\)-join                           :: BalBST k a -> BalBST k a -> BalBST k a-join (BalBST n l) (BalBST _ r) = BalBST n $ joinWith n l r---- | Joins two BSTs' with a specific Tree Navigator------ \(O(\log n)\)-joinWith               :: TreeNavigator k a -> Tree k a -> Tree k a -> Tree k a-joinWith Nav{..} tl tr-    | lh >= rh         = blacken $ joinL tl tr-    | otherwise        = blacken $ joinR tl tr-  where-    rh = height tr-    lh = height tl--    joinL Empty      _           = Empty-    joinL l          Empty       = l-    joinL l@(Leaf x) r@(Leaf y)  = red 2 l (extractKey x y) r-    joinL l@(Node c h ll k lr) r-      | h == rh                  = let lm = unsafeMax lr-                                       rm = unsafeMin r-                                   in balance Red (h+1) l (extractKey lm rm) r-      | otherwise                = balance c h ll k (joinL lr r)-        -- lh >= rh-    joinL _ _ = error "joinL. absurd"---    joinR _          Empty       = Empty-    joinR Empty      r           = r--    joinR l@(Leaf x) r@(Leaf y)  = red 2 l (extractKey x y) r-    joinR l r@(Node c h rl k rr)-      | h == lh                  = let lm = unsafeMax l-                                       rm = unsafeMin rl-                                   in balance Red (h+1) l (extractKey lm rm) r-      | otherwise                = balance c h (joinR l rl) k rr-        -- lh >= rh-    joinR _ _ = error "joinR absurd"-------------------------------------------------------------------------------------- | Splitting and extracting---- | A pair that is strict in its first argument and lazy in the second.-data Pair a b = Pair { fst' :: !a-                     , snd' :: b-                     } deriving (Show,Eq,Functor,Foldable,Traversable)---collect        :: b -> [Pair a b] -> Pair [a] b-collect def [] = Pair [] def-collect _   xs = Pair (map fst' xs) (snd' $ last xs)----- | Extract a prefix from the tree, i.e. a repeated 'minView'------ \(O(\log n +k)\), where \(k\) is the size of the extracted part-extractPrefix                      :: BalBST k a -> [Pair a (Tree k a)]-extractPrefix (BalBST n@Nav{..} t) = extractPrefix' t-  where-    extractPrefix' Empty            = []-    extractPrefix' (Leaf x)         = [Pair x Empty]-    extractPrefix' (Node _ _ l _ r) = ls ++ extractPrefix' r-      where-        ls = map (fmap $ flip (joinWith n) r) $ extractPrefix' l---- | Extract a suffix from the tree, i.e. a repeated 'minView'------ \(O(\log n +k)\), where \(k\) is the size of the extracted part-extractSuffix                      :: BalBST k a -> [Pair a (Tree k a)]-extractSuffix (BalBST n@Nav{..} t) = extract t-  where-    extract Empty            = []-    extract (Leaf x)         = [Pair x Empty]-    extract (Node _ _ l _ r) = rs ++ extract l-      where-        rs = map (fmap $ joinWith n l) $ extract r---- | Result of splititng a tree-data Split a b = Split a !b a deriving (Show,Eq)---- | Splits the tree at x. Note that if x occurs more often, no guarantees are--- given which one is found.------ \(O(\log n)\)-split                        :: Eq a => a -> BalBST k a -> Split (Tree k a) (Maybe a)-split x (BalBST n@Nav{..} t) = split' t-  where-    split' Empty                  = Split Empty Nothing Empty-    split' l@(Leaf y)-      | x == y                    = Split Empty (Just y) Empty-      | goLeft x (extractKey x y) = Split l     Nothing  Empty-      | otherwise                 = Split Empty Nothing  l-    split' (Node _ _ l k r)-      | goLeft x k                = let Split l' mx r' = split' l-                                    in Split l' mx (joinWith n r' r)-      | otherwise                 = let Split l' mx r' = split' r-                                    in Split (joinWith n l l') mx r'---- | split based on a monotonic predicate------ \(O(\log n)\)-splitMonotone                        :: (a -> Bool) -> BalBST k a-                                     -> (BalBST k a, BalBST k a)-splitMonotone p (BalBST n@Nav{..} t) = bimap (BalBST n) (BalBST n) $ split' t-  where-    split' Empty        = (Empty,Empty)-    split' l@(Leaf y)-      | p y             = (Empty,l)-      | otherwise       = (l,Empty)-    split' (Node _ _ l _ r)-      | p (unsafeMin r) = let (l',m) = split' l in (l',joinWith n m r)-      | otherwise       = let (m,r') = split' r in (joinWith n l m, r')----- | Splits at a given monotone predicate p, and then selects everything that--- satisfies the predicate sel.-splitExtract           :: (a -> Bool) -> (a -> Bool) -> BalBST k a-                       -> Split (BalBST k a) ([a],[a])-splitExtract p sel bst = Split (BalBST n before) (reverse mid1,mid2) (BalBST n after)-  where-    n                = nav bst-    (before',after') = splitMonotone p bst--    extract def = collect def . L.takeWhile (sel . fst')--    Pair mid1 before = extract (toTree before') $ extractSuffix before'-    Pair mid2 after  = extract (toTree after')  $ extractPrefix after'--------------------------------------------------------------------------------------data T k a = Internal !Color !Height !k | Val !a deriving (Show,Eq,Ord)--toRoseTree :: Tree k a -> Maybe (T.Tree (T k a))-toRoseTree Empty            = Nothing-toRoseTree (Leaf x)         = Just $ T.Node (Val x) []-toRoseTree (Node c h l k r) = Just $ T.Node (Internal c h k) (mapMaybe toRoseTree [l,r])---showTree :: (Show k, Show a) => BalBST k a -> String-showTree = maybe "Empty" T.drawTree . fmap (fmap show) . toRoseTree . toTree---- | Get the minimum in the tree. Errors when the tree is empty------ \(O(\log n)\)-unsafeMin                  :: Tree k a -> a-unsafeMin (Leaf x)         = x-unsafeMin (Node _ _ l _ _) = unsafeMin l-unsafeMin _                = error "unsafeMin: Empty"---- | Get the maximum in the tree. Errors when the tree is empty------ \(O(\log n)\)-unsafeMax                  :: Tree k a -> a-unsafeMax (Leaf x)         = x-unsafeMax (Node _ _ _ _ r) = unsafeMax r-unsafeMax _                = error "unsafeMax: Empty"---- | Extract all elements in the tree------ \(O(n)\)-toList :: BalBST k a -> [a]-toList = toList' . toTree---- | Extract all elements in the tree------ \(O(n)\)-toList'                  :: Tree k a -> [a]-toList' Empty            = []-toList' (Leaf x)         = [x]-toList' (Node _ _ l _ r) = toList' l ++ toList' r-------------------------------------------------------------------------------------- * Helper stuff--black :: Height -> Tree k a -> k -> Tree k a -> Tree k a-black = Node Black--red :: Height -> Tree k a -> k -> Tree k a -> Tree k a-red = Node Red---blacken                    :: Tree k a -> Tree k a-blacken (Node Red h l k r) = Node Black h l k r-blacken t                  = t---- | rebalance the tree-balance  :: Color -> Height -> Tree k a -> k -> Tree k a -> Tree k a-balance Black h (Node Red _ (Node Red _ a x b) y c) z d = mkNode h a x b y c z d-balance Black h (Node Red _ a x (Node Red _ b y c)) z d = mkNode h a x b y c z d-balance Black h a x (Node Red _ (Node Red _ b y c) z d) = mkNode h a x b y c z d-balance Black h a x (Node Red _ b y (Node Red _ c z d)) = mkNode h a x b y c z d-balance co h a x b                                      = Node co h a x b--mkNode                 :: Height-                       -> Tree k a -> k -> Tree k a -> k -> Tree k a  -> k -> Tree k a-                       -> Tree k a-mkNode h a x b y c z d = red h (black h a x b) y (black h c z d)--height                  :: Tree k a -> Height-height Empty            = 0-height (Leaf _)         = 1-height (Node _ h _ _ _) = h
src/Data/BinaryTree.hs view
@@ -1,5 +1,4 @@ {-# Language DeriveFunctor#-}-{-# Language FunctionalDependencies #-} -------------------------------------------------------------------------------- -- | -- Module      :  Data.BinaryTree@@ -17,12 +16,14 @@ import           Data.Bifunctor.Apply import           Data.List.NonEmpty (NonEmpty) import           Data.Maybe (mapMaybe)+import           Data.Measured.Class+import           Data.Measured.Size import           Data.Semigroup.Foldable import qualified Data.Tree as Tree+import           Data.Tree.Util (TreeNode(..)) import qualified Data.Vector as V import           GHC.Generics (Generic) import           Test.QuickCheck- --------------------------------------------------------------------------------  -- | Binary tree that stores its values (of type a) in the leaves. Internal@@ -33,9 +34,6 @@  instance (NFData v, NFData a) => NFData (BinLeafTree v a) -class Semigroup v => Measured v a | a -> v where-  measure :: a -> v- -- | smart constructor node     :: Measured v a => BinLeafTree v a -> BinLeafTree v a -> BinLeafTree v a node l r = Node l (measure l <> measure r) r@@ -116,50 +114,19 @@ zipExactWith _ _ _            _               =     error "zipExactWith: tree structures not the same " -newtype Size = Size Int deriving (Show,Read,Eq,Num,Integral,Enum,Real,Ord,Generic,NFData) -instance Semigroup Size where-  x <> y = x + y -instance Monoid Size where-  mempty = Size 0-  mappend = (<>)--newtype Elem a = Elem { _unElem :: a }-               deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)--instance Measured Size (Elem a) where-  measure _ = 1---data Sized a = Sized !Size a-             deriving (Show,Eq,Ord,Functor,Foldable,Traversable,Generic)-instance NFData a => NFData (Sized a)--instance Semigroup a => Semigroup (Sized a) where-  (Sized i a) <> (Sized j b) = Sized (i <> j) (a <> b)--instance Monoid a => Monoid (Sized a) where-  mempty = Sized mempty mempty-  (Sized i a) `mappend` (Sized j b) = Sized (i <> j) (a `mappend` b)---- instance Semigroup a => Measured Size (Sized a) where---   measure (Sized i _) = i-- -------------------------------------------------------------------------------- -- * Converting into a Data.Tree -data RoseElem v a = InternalNode v | LeafNode a deriving (Show,Eq,Functor)--toRoseTree              :: BinLeafTree v a -> Tree.Tree (RoseElem v a)+-- | \( O(n) \) Convert binary tree to a rose tree, aka 'Tree.Tree'.+toRoseTree              :: BinLeafTree v a -> Tree.Tree (TreeNode v a) toRoseTree (Leaf x)     = Tree.Node (LeafNode x) [] toRoseTree (Node l v r) = Tree.Node (InternalNode v) (map toRoseTree [l,r]) -+-- | 2-dimensional ASCII drawing of a tree. drawTree :: (Show v, Show a) => BinLeafTree v a -> String drawTree = Tree.drawTree . fmap show . toRoseTree-  -------------------------------------------------------------------------------- -- * Internal Node Tree
− src/Data/BinaryTree/Zipper.hs
@@ -1,64 +0,0 @@-module Data.BinaryTree.Zipper where--import Data.BinaryTree------------------------------------------------------------------------------------data Ctx a = Top | L (Ctx a) a (BinaryTree a) | R (BinaryTree a) a (Ctx a)-           deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)--data BinaryTreeZipper a = Loc (BinaryTree a) (Ctx a)-           deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)---- | Focus on the root-top   :: BinaryTree a -> BinaryTreeZipper a-top t = Loc t Top---- | Go to the left child-left                            :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-left (Loc (Internal l x r) ctx) = Just $ Loc l (L ctx x r)-left (Loc Nil _)                = Nothing---- | Go to the right child-right                            :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-right (Loc (Internal l x r) ctx) = Just $ Loc r (R l x ctx)-right (Loc Nil _)                = Nothing---- | Move to the parent-up                     :: BinaryTreeZipper a -> Maybe (BinaryTreeZipper a)-up (Loc _ Top)         = Nothing-up (Loc l (L ctx x r)) = Just $ Loc (Internal l x r) ctx-up (Loc r (R l x ctx)) = Just $ Loc (Internal l x r) ctx---- | Navigate to the root-toRoot   :: BinaryTreeZipper a -> BinaryTreeZipper a-toRoot z = toRoot' z (Just z)-  where-    toRoot' z' Nothing   = z'-    toRoot' _  (Just z') = toRoot' z' (up z')----- | Returns a list of zippers; one focussed on each node in the tree-visitAll   :: BinaryTree a -> [BinaryTreeZipper a]-visitAll t = visitAll' (top t)-  where-    f           = maybe [] visitAll'-    visitAll' z = z : f (left z) <> f (right z)---- | Get the value stored at the current node-accessZ           :: BinaryTreeZipper a -> Maybe a-accessZ (Loc t _) = access t----- | Returns all subtrees; i.e. every node with all its decendents-subTrees :: BinaryTree a -> [BinaryTree a]-subTrees t = Nil : subTrees' t-  where-    subTrees' Nil                 = []-    subTrees' tt@(Internal l _ r) = tt : subTrees' l <> subTrees' r----- | Splits the tree here, returns a pair (innerTree,outerTree)-splitTree             :: BinaryTreeZipper a -> (BinaryTree a, BinaryTree a)-splitTree (Loc t ctx) = let (Loc r _) = toRoot $ Loc Nil ctx-                        in (t, r)
src/Data/CircularList/Util.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.CircularList.Util+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Data.CircularList.Util where  import           Control.Lens@@ -43,14 +50,14 @@ insertOrdBy'         :: (a -> a -> Ordering) -> a -> [a] -> [a] insertOrdBy' cmp x xs = case (rest, x `cmp` head rest) of     ([],  _)   -> L.insertBy cmp x pref-    (z:zs, GT) -> (z : L.insertBy cmp x zs) ++ pref-    (_:_,  EQ) -> (x : xs) -- == x : rest ++ pref+    (z:zs, GT) -> z : L.insertBy cmp x zs ++ pref+    (_:_,  EQ) -> x : xs -- == x : rest ++ pref     (_:_,  LT) -> rest ++ L.insertBy cmp x pref   where     -- split the list at its maximum.     (pref,rest) = splitIncr cmp xs --- given a list of elements that is supposedly a a cyclic-shift of a list of+-- | Given a list of elements that is supposedly a a cyclic-shift of a list of -- increasing items, find the splitting point. I.e. returns a pair of lists -- (ys,zs) such that xs = zs ++ ys, and ys ++ zs is (supposedly) in sorted -- order.
src/Data/CircularSeq.hs view
@@ -1,3 +1,10 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.CircularSeq+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Data.CircularSeq( CSeq                        , cseq                        , singleton@@ -15,6 +22,7 @@                        , rightElements                        , leftElements                        , asSeq+                       , withIndices                         , reverseDirection                        , allRotations@@ -32,18 +40,20 @@  import           Algorithms.StringSearch.KMP (isSubStringOf) import           Control.DeepSeq-import           Control.Lens (lens, Lens', bimap)+import           Control.Lens (Lens', bimap, lens)+import           Data.Ext import qualified Data.Foldable as F import qualified Data.List as L import qualified Data.List.NonEmpty as NonEmpty-import           Data.Maybe (listToMaybe, isJust)+import           Data.Maybe (isJust) import           Data.Semigroup.Foldable-import           Data.Sequence ((|>),(<|),ViewL(..),ViewR(..),Seq)+import           Data.Sequence               (Seq, ViewL (..), ViewR (..), (<|),+                                              (|>)) import qualified Data.Sequence as S import qualified Data.Traversable as T import           Data.Tuple (swap) import           GHC.Generics (Generic)-import           Test.QuickCheck(Arbitrary(..))+import           Test.QuickCheck (Arbitrary (..)) import           Test.QuickCheck.Instances ()  --------------------------------------------------------------------------------@@ -67,6 +77,11 @@                     showString (("CSeq " <>) . show . F.toList . rightElements $ s)     where app_prec = 10 +instance Read a => Read (CSeq a) where+  readsPrec d = readParen (d > app_prec) $ \r ->+      [ (fromList lst, t) | ("CSeq", s) <- lex r, (lst, t) <- reads s ]+    where app_prec = 10+ -- traverses starting at the focus, going to the right. instance T.Traversable CSeq where   traverse f (CSeq l x r) = (\x' r' l' -> CSeq l' x' r')@@ -87,15 +102,18 @@ instance Arbitrary a => Arbitrary (CSeq a) where   arbitrary = CSeq <$> arbitrary <*> arbitrary <*> arbitrary +-- | /O(1)/ CSeq with exactly one element. singleton   :: a -> CSeq a singleton x = CSeq S.empty x S.empty --- | Gets the focus of the CSeq+-- | Gets the focus of the CSeq.+-- -- running time: O(1) focus              :: CSeq a -> a focus (CSeq _ x _) = x --- | Access the i^th item  (w.r.t the focus) in the CSeq (indices modulo n).+-- | Access the i^th item (w.r.t the focus; elements numbered in+-- increasing order towards the right) in the CSeq (indices modulo n). -- -- running time: \(O(\log (i \mod n))\) --@@ -120,6 +138,15 @@                                else if i - 1 < rn then S.index r (i - 1)                                                   else S.index l (i - rn - 1) +-- | Label the elements with indices.+--+-- >>> withIndices $ fromList [0..5]+-- CSeq [0 :+ 0,1 :+ 1,2 :+ 2,3 :+ 3,4 :+ 4,5 :+ 5]+withIndices              :: CSeq a -> CSeq (Int :+ a)+withIndices (CSeq l x r) = let s = 1 + length r in+  CSeq (S.mapWithIndex (\i y -> i + s :+ y) l) (0 :+ x) (S.mapWithIndex (\i y -> i+1 :+ y) r)++ -- | Adjusts the i^th element w.r.t the focus in the CSeq -- -- running time: \(O(\log (i \mod n))\)@@ -135,9 +162,9 @@                                      else CSeq (S.adjust f (i - rn - 1) l) x r  --- | Access te ith item in the CSeq (w.r.t the focus) as a lens+-- | Access the ith item in the CSeq (w.r.t the focus) as a lens item   :: Int -> Lens' (CSeq a) a-item i = lens (flip index i) (\s x -> adjust (const x) i s)+item i = lens (`index` i) (\s x -> adjust (const x) i s)   resplit   :: Seq a -> (Seq a, Seq a)@@ -194,8 +221,8 @@ rotateL                :: CSeq a -> CSeq a rotateL s@(CSeq l x r) = case S.viewr l of                            EmptyR    -> case S.viewr r of-                             EmptyR     -> s-                             (r' :> y)  -> cseq r' y (S.singleton x)+                             EmptyR    -> s+                             (r' :> y) -> cseq r' y (S.singleton x)                            (l' :> y) -> cseq l' y (x <| r)  @@ -223,6 +250,11 @@ fromNonEmpty                    :: NonEmpty.NonEmpty a -> CSeq a fromNonEmpty (x NonEmpty.:| xs) = withFocus x $ S.fromList xs +{- HLINT ignore fromList -}+-- | /O(n)/ Convert from a list to a CSeq.+--+-- Warning: the onus is on the user to ensure that their list+-- is not empty, otherwise all bets are off! fromList        :: [a] -> CSeq a fromList (x:xs) = withFocus x $ S.fromList xs fromList []     = error "fromList: Empty list"@@ -266,7 +298,7 @@                     S.EmptyR -> let (y :< r') = S.viewl r in cseq l' y r'  --- | Reversres the direction of the CSeq+-- | Reverses the direction of the CSeq -- -- running time: \(O(n)\) --@@ -283,9 +315,9 @@ -- >>> findRotateTo (== 7) $ fromList [1..5] -- Nothing findRotateTo   :: (a -> Bool) -> CSeq a -> Maybe (CSeq a)-findRotateTo p = listToMaybe . filter (p . focus) . allRotations'-+findRotateTo p = L.find (p . focus) . allRotations' +-- | Rotate to a specific element in the CSeq. rotateTo   :: Eq a => a -> CSeq a -> Maybe (CSeq a) rotateTo x = findRotateTo (== x) @@ -354,8 +386,8 @@ insertOrdBy'         :: (a -> a -> Ordering) -> a -> [a] -> [a] insertOrdBy' cmp x xs = case (rest, x `cmp` head rest) of     ([],  _)   -> L.insertBy cmp x pref-    (z:zs, GT) -> (z : L.insertBy cmp x zs) ++ pref-    (_:_,  EQ) -> (x : xs) -- == x : rest ++ pref+    (z:zs, GT) -> z : L.insertBy cmp x zs ++ pref+    (_:_,  EQ) -> x : xs -- == x : rest ++ pref     (_:_,  LT) -> rest ++ L.insertBy cmp x pref   where     -- split the list at its maximum.
+ src/Data/Double/Approximate.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE MagicHash           #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | See: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/+module Data.Double.Approximate+  ( SafeDouble+  , DoubleRelAbs(..)+  ) where++import Control.DeepSeq+import Data.Proxy+import GHC.TypeLits+import Numeric.MathFunctions.Comparison+import Numeric.MathFunctions.Constants+import System.Random+import Text.Read++-- | Relatively safe double floating-point type with a relative error+--   margin of 10 <https://en.wikipedia.org/wiki/Unit_in_the_last_place ULPs>+--   and an absolute margin around zero of+--   @10*<https://en.wikipedia.org/wiki/Machine_epsilon epsilon>@.+--+--   Warning: All numbers within+--   @10*<https://en.wikipedia.org/wiki/Machine_epsilon epsilon>@ of zero will be considered zero.+--+-- >>> m_epsilon * 10+-- 2.220446049250313e-15+--+-- >>> realToFrac (m_epsilon * 10) == (0::SafeDouble)+-- False+--+-- >>> realToFrac (m_epsilon * 9) == (0::SafeDouble)+-- True+--+-- >>> 1e-20 == (5e-20 :: Double)+-- False+-- >>> 1e-20 == (5e-20 :: SafeDouble)+-- True+--+-- 'pi' and 'sin' are approximations:+--+-- >>> sin pi+-- 1.2246467991473532e-16+--+-- >>> sin pi == (0 :: Double)+-- False+--+-- >>> sin pi == (0 :: SafeDouble)+-- True+--+type SafeDouble = DoubleRelAbs 10 10++-- | Custom double floating-point type with a relative error margin of+--   @rel@ number of+--   <https://en.wikipedia.org/wiki/Unit_in_the_last_place ULPs> and an+--   absolute error margin of @abs@ times+--   <https://en.wikipedia.org/wiki/Machine_epsilon epsilon>.+--+--   The relative error margin is the primary tool for good numerical+--   robustness and can relatively safely be set to a high number such+--   as 100. The absolute error margin is a last ditch attempt at fixing+--   broken algorithms and dramatically limits the resolution around zero.+--   If possible, use a low absolute error margin.+newtype DoubleRelAbs (abs :: Nat) (rel :: Nat) = DoubleRelAbs Double+  deriving (Num, Enum, Floating, Fractional, Real, RealFloat, RealFrac, Random, NFData)++instance (KnownNat abs, KnownNat rel) => Eq (DoubleRelAbs abs rel) where+  DoubleRelAbs d1 == DoubleRelAbs d2 =+    within (fromIntegral (natVal @rel Proxy)) d1 d2 ||+    (abs d1 < m_epsilon * fromIntegral (natVal @abs Proxy) &&+     abs d2 < m_epsilon * fromIntegral (natVal @abs Proxy))++instance (KnownNat abs, KnownNat rel) => Ord (DoubleRelAbs abs rel) where+  lhs@(DoubleRelAbs d1) `compare` rhs@(DoubleRelAbs d2)+    | lhs == rhs = EQ+    | otherwise  = d1 `compare` d2++instance Show (DoubleRelAbs abs rel) where+  showsPrec i (DoubleRelAbs d) = showsPrec i d++instance Read (DoubleRelAbs abs rel) where+  readPrec = DoubleRelAbs <$> readPrec+
+ src/Data/Double/Shaman.hs view
@@ -0,0 +1,295 @@+-- https://tel.archives-ouvertes.fr/tel-03116750/document+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+module Data.Double.Shaman+  ( Shaman+  , significativeBits+  , significativeDigits+  , SDouble+  ) where++import Numeric.MathFunctions.Comparison ( addUlps)+import Numeric.MathFunctions.Constants+import GHC.TypeLits+import Data.Double.Approximate++-- | Double-precision floating point numbers that throw exceptions if+--   the accumulated errors grow large enough to cause unstable branching.+--+--   If @SDouble n@ works without throwing any exceptions, it'll be safe to+--   use @DoubleRelAbs n 0@ instead for a sizable performance boost.+--+-- >>> sin pi == (0 :: SDouble 0)+-- *** Exception: Insufficient precision.+-- ...+--+-- @SDouble 0@ failed so @DoubleRelAbs 0 0@ will lead to an unstable branch. In+-- other words, it'll return @False@ when it should have returned @True@:+--+-- >>> sin pi == (0 :: DoubleRelAbs 0 0)+-- False+--+-- Comparing to within 1 ULP stabalizes the branch:+--+-- >>> sin pi == (0 :: SDouble 1)+-- True+--+-- >>> sin pi == (0 :: DoubleRelAbs 1 0)+-- True+--+newtype SDouble (n::Nat) = SDouble Shaman+  deriving (Num, Fractional, Floating, Real, RealFrac, RealFloat)++instance Show (SDouble n) where+  showsPrec d (SDouble s) = showsPrec d s++instance Read (SDouble n) where+  readsPrec d inp = [ (SDouble v, r) | (v, r) <- readsPrec d inp ]+++-- shamanUlpDistance :: Shaman -> Word64+-- shamanUlpDistance (Shaman n e) = ulpDistance n (n+e)++compareSDouble :: KnownNat n => SDouble n -> SDouble n -> Ordering+compareSDouble a@(SDouble a') b@(SDouble b')+   | a == b    = EQ+   | otherwise = shamanValue a' `compare` shamanValue b'++toDoubleRelAbs :: SDouble n -> DoubleRelAbs n 0+toDoubleRelAbs (SDouble (Shaman v _e)) = DoubleRelAbs v++-- If (a :: DoubleRelAbs n 0) == (b :: DoubleRelAbs n 0)+instance KnownNat n => Eq (SDouble n) where+  a@(SDouble a') == b@(SDouble b')+    | blessedResult == approxResult = blessedResult+    | otherwise                     = error "Insufficient precision."+    where+      blessedResult = a' == b'+      approxResult = toDoubleRelAbs a == toDoubleRelAbs b++instance KnownNat n => Ord (SDouble n) where+  compare = compareSDouble++++++-- | Double-precision floating point numbers with error-bounds.+--+-- Some digits can be represented exactly and have essentially an infinitely number of significant digits:+--+-- >>> significativeDigits 1+-- Infinity+--+-- Some fractional numbers can also be represented exactly:+--+-- >>> significativeDigits 0.5+-- Infinity+--+-- Other numbers are merely approximations:+--+-- >>> significativeDigits 0.1+-- 16.255619765854984+--+-- Pi is an irrational number so we can't represent it with infinite precision:+--+-- >>> significativeDigits pi+-- 15.849679651557175+--+-- @sin pi@ should theoretically be zero but we cannot do better than saying it is near zero:+--+-- >>> sin pi+-- 1.2246467991473532e-16+--+-- The error margins are greater than value itself so we have no significant digits:+--+-- >>> significativeDigits (sin pi)+-- 0.0+--+-- Since 'near zero' is not zero, the following fails when using Doubles:+--+-- >>> sin pi == (0 :: Double)+-- False+--+-- Equality testing for Shaman numbers tests whether the two intervals+-- overlap:+--+-- >>> sin pi == (0 :: Shaman)+-- True+data Shaman = Shaman+  { shamanValue :: {-# UNPACK #-} !Double+  , shamanError :: {-# UNPACK #-} !Double+  }++instance Show Shaman where+  showsPrec d Shaman{..} = showParen (d > 10) $+    shows shamanValue . showChar '±' . shows shamanError++instance Read Shaman where+  readsPrec d = readParen (d > app_prec) $ \r ->+      [ (Shaman{..}, t')+      | (shamanValue, '±':t) <- reads r+      , (shamanError, t') <- reads t]+    where app_prec = 10++-- | Number of significant bits (base 2).+significativeBits :: Shaman -> Double+significativeBits v = significativeValue v / log 2++-- | Number of significant digits (base 10).+significativeDigits :: Shaman -> Double+significativeDigits v = significativeValue v / log 10++significativeValue :: Shaman -> Double+significativeValue (Shaman v e)+  | e == 0    = m_pos_inf+  | isNaN e   = 0+  | v == 0    = max 0 (log (abs e - 1))+  | otherwise =+    let relError = abs (e / v) in+    if relError >= 1+      then 0+      else negate $ log relError++instance Num Shaman where+  Shaman x dx + Shaman y dy =+    case x+y of+      !xy -> Shaman xy (dx+dy+twoSum x y xy)++  Shaman x dx * Shaman y dy =+    case x*y of+      !z -> Shaman z (dx * y + dy * x + fma x y (-z))+  +  abs (Shaman x dx) = Shaman (abs x) dx++  signum (Shaman x dx) = Shaman (signum x) dx++  negate (Shaman x dx) = Shaman (negate x) dx++  fromInteger i =+    let d = fromInteger i+    in Shaman d (abs $ realToFrac $ i - round d)++instance Fractional Shaman where+  Shaman x dx / Shaman y dy =+    let z = x/y+        numerator = dx - fma y z (-x) - z * dy+        denominator = y + dy+    in Shaman z (numerator / denominator)+  fromRational r =+    let d = fromRational r+    in Shaman d (abs $ realToFrac $ r - realToFrac d)++instance Floating Shaman where+  pi = Shaman pi (addUlps 1 pi - pi)+  sqrt (Shaman x dx)+    | z == 0, dx == 0 =+      Shaman z 0+    | z == 0 =+      Shaman z (sqrt (abs dx)) -- FIXME: Use long double.+    | otherwise =+      Shaman z ((r + dx) / (z+z))+    where+      r = negate $ fma z z (negate x)+      z = sqrt x+  log = foreignOp erf_log log+  exp = foreignOp erf_exp exp+  (**) = foreignBinOp erf_pow (**)+  sin = foreignOp erf_sin sin+  cos = foreignOp erf_cos cos+  tan = foreignOp erf_tan tan+  asin = foreignOp erf_asin asin+  acos = foreignOp erf_acos acos+  atan = foreignOp erf_atan atan+  sinh = foreignOp erf_sinh sinh+  cosh = foreignOp erf_cosh cosh+  tanh = foreignOp erf_tanh tanh+  asinh = foreignOp erf_asinh asinh+  acosh = foreignOp erf_acosh acosh+  atanh = foreignOp erf_atanh atanh++instance Real Shaman where+  toRational (Shaman v _) = toRational v++instance RealFrac Shaman where+  properFraction (Shaman v e) =+    case properFraction v of+      (i, v') -> (i, Shaman v' e)+  truncate (Shaman v _e) = truncate v+  round (Shaman v _e) = round v+  ceiling (Shaman v e) = ceiling (v+e)+  floor (Shaman v e) = floor (v-e)++instance RealFloat Shaman where+  floatRadix = floatRadix . shamanValue+  floatDigits = floatDigits . shamanValue+  floatRange = floatRange . shamanValue+  decodeFloat = decodeFloat . shamanValue+  encodeFloat m e = Shaman (encodeFloat m e) 0 -- FIXME: 1 ULP error bound?+  exponent = exponent . shamanValue+  significand s = Shaman (significand $ shamanValue s) 0+  scaleFloat p (Shaman v e) = Shaman (scaleFloat p v) e+  isNaN = isNaN . shamanValue+  isInfinite = isInfinite . shamanValue+  isDenormalized = isDenormalized . shamanValue+  isNegativeZero = isNegativeZero . shamanValue+  isIEEE = isIEEE . shamanValue+  atan2 = foreignBinOp erf_atan2 atan2+++instance Eq Shaman where+  x == y = compareShaman x y == EQ++instance Ord Shaman where+  compare = compareShaman++-- Returns EQ iff the two numbers overlap.+compareShaman :: Shaman -> Shaman -> Ordering+compareShaman (Shaman x dx) (Shaman y dy)+  | abs (x-y) < abs dx+ abs dy = EQ+  | x < y             = LT+  | otherwise         = GT++twoSum :: Double -> Double -> Double -> Double+twoSum x y xy = abs (x-x') + abs (y-y')+  where+    x' = xy-y+    y' = xy-x++foreignOp :: (Double -> Double -> Double -> Double) -> (Double -> Double) -> Shaman -> Shaman+foreignOp mkDelta fn (Shaman x dx) =+  let !z = fn x+  in Shaman z (abs $ mkDelta x dx z)++foreignBinOp ::+    (Double -> Double -> Double -> Double -> Double -> Double) ->+    (Double -> Double -> Double) ->+    Shaman -> Shaman -> Shaman+foreignBinOp mkDelta fn (Shaman x dx) (Shaman y dy) =+  let !z = fn x y+  in Shaman z (mkDelta x dx y dy z)++foreign import ccall unsafe "fma" fma :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_log" erf_log :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_exp" erf_exp :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_pow" erf_pow :: Double -> Double -> Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_sin" erf_sin :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_cos" erf_cos :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_tan" erf_tan :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_asin" erf_asin :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_acos" erf_acos :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_atan" erf_atan :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_sinh" erf_sinh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_cosh" erf_cosh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_tanh" erf_tanh :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_asinh" erf_asinh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_acosh" erf_acosh :: Double -> Double -> Double -> Double+foreign import ccall unsafe "erf_atanh" erf_atanh :: Double -> Double -> Double -> Double++foreign import ccall unsafe "erf_atan2" erf_atan2 :: Double -> Double -> Double -> Double -> Double -> Double
src/Data/DynamicOrd.hs view
@@ -1,6 +1,14 @@ {-# LANGUAGE UndecidableInstances #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.DynamicOrd+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Data.DynamicOrd where +import Data.Kind import Data.Proxy import Data.Reflection import Unsafe.Coerce@@ -10,8 +18,8 @@ -- Implementation from -- https://www.schoolofhaskell.com/user/thoughtpolice/using-reflection --- | Values of type 'a' in our dynamically constructed 'Ord' instance-newtype O (s :: *) (a :: *) = O { runO :: a } deriving (Show)+-- | Values of type '@a@' in our dynamically constructed 'Ord' instance+newtype O (s :: Type) (a :: Type) = O { runO :: a } deriving (Show)  -- | An Ord Dictionary newtype OrdDict a = OrdDict { compare_ :: a -> a -> Ordering }@@ -37,35 +45,35 @@ -- * Introducing and removing the dynamic order type -- Note that all of these may be unsafe if used incorrectly --- | Lifts a container f whose values (of type a) depend on 's' into a--- more general computation in that produces a 'f a' (depending on s).+-- | Lifts a container f whose values (of type a) depend on '@s@' into a+-- more general computation in that produces a '@f a@' (depending on s). -- -- running time: \(O(1)\) extractOrd1 :: f (O s a) -> O s (f a) extractOrd1 = unsafeCoerce  --- | Introduce dynamic order in a container 'f'.+-- | Introduce dynamic order in a container '@f@'. -- -- running time: \(O(1)\) introOrd1 :: f a -> f (O s a) introOrd1 = unsafeCoerce --- | Lifts a function that works on a container 'f' of+-- | Lifts a function that works on a container '@f@' of -- orderable-things into one that works on dynamically ordered ones.-liftOrd1   :: (f (O s a) -> f (O s a))-           -> f a -> O s (f a)+liftOrd1   :: (f (O s a) -> g (O s a))+           -> f a -> O s (g a) liftOrd1 f = extractOrd1 . f . introOrd1  --- | Lifts a container f whose keys (of type k) depend on 's' into a--- more general computation in that produces a 'f k v' (depending on s).+-- | Lifts a container f whose keys (of type k) depend on '@s@' into a+-- more general computation in that produces a @`f k v`@ (depending on s). -- -- running time: \(O(1)\) extractOrd2 :: f (O s k) v -> O s (f k v) extractOrd2 = unsafeCoerce --- | Introduce dynamic order in a container 'f' that has keys of type+-- | Introduce dynamic order in a container '@f@' that has keys of type -- k. -- -- running time: \(O(1)\)
src/Data/Ext.hs view
@@ -21,6 +21,7 @@ import Data.Bifoldable import Data.Bifunctor.Apply import Data.Bitraversable+-- import Data.Default import Data.Functor.Apply (liftF2) import Data.Semigroup.Bifoldable import Data.Semigroup.Bitraversable@@ -74,17 +75,30 @@ instance (Arbitrary c, Arbitrary e) => Arbitrary (c :+ e) where   arbitrary = (:+) <$> arbitrary <*> arbitrary +-- instance (Default a, Default b) => Default (a :+ b) where+--   def = def :+ def++-- | Access the core of an extended value. _core :: (core :+ extra) -> core _core (c :+ _) = c+{-# INLINABLE _core #-} +-- | Access the extra part of an extended value. _extra :: (core :+ extra) -> extra _extra (_ :+ e) = e+{-# INLINABLE _extra #-} +-- | Lens access to the core of an extended value. core :: Lens (core :+ extra) (core' :+ extra) core core'-core = lens _core (\(_ :+ e) c -> (c :+ e))+core = lens _core (\(_ :+ e) c -> c :+ e)+{-# INLINABLE core #-} +-- | Lens access to the extra part of an extended value. extra :: Lens (core :+ extra) (core :+ extra') extra extra'-extra = lens _extra (\(c :+ _) e -> (c :+ e))+extra = lens _extra (\(c :+ _) e -> c :+ e)+{-# INLINABLE extra #-} +-- | Tag a value with the unit type. ext   :: a -> a :+ () ext x = x :+ ()+{-# INLINABLE ext #-}
+ src/Data/IndexedDoublyLinkedList.hs view
@@ -0,0 +1,216 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.IndexedDoublyLinkedList+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.IndexedDoublyLinkedList( DLList(..)+                                   , Cell(..), emptyCell+                                   , DLListMonad, runDLListMonad+                                   , Index++                                   , singletons+                                   , writeList+                                   , valueAt, getNext, getPrev+                                   , toListFrom, toListFromR, toListContains+                                   , toListFromK, toListFromRK+                                   , insertAfter, insertBefore+                                   , delete+                                   , dump+                                   ) where++import           Control.Monad.Primitive (PrimMonad(..))+import           Control.Monad.Reader (ReaderT, runReaderT)+import           Control.Monad.Reader.Class+import           Control.Monad.ST+import           Data.Foldable (forM_)+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.Util+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV++--------------------------------------------------------------------------------++-- | Cell indices. Must be non-negative.+type Index = Int++-- TODO: Switch to unobxed sums for these!++-- | Cells in the Linked List+data Cell = Cell { prev :: Maybe Index+                 , next :: Maybe Index+                 } deriving (Show,Eq)++-- | Empty cell with no next or prev cells.+emptyCell :: Cell+emptyCell = Cell Nothing Nothing++-- | Doubly linked list implemented by a mutable vector. So actually+-- this data type can represent a collection of Linked Lists that can+-- efficiently be concatenated and split.+--+-- Supports O(1) indexing, and O(1) insertions, deletions+data DLList s a = DLList { values :: !(V.Vector a)+                         , llist  :: !(MV.MVector s Cell)+                         }++instance Functor (DLList s) where+  fmap f (DLList v l) = DLList (fmap f v) l+++--------------------------------------------------------------------------------++-- | Monad in which we can use the IndexedDoublyLinkedList.+newtype DLListMonad s b a = DLListMonad { runDLListMonad' :: ReaderT (DLList s b) (ST s) a }+                         deriving (Functor,Applicative,Monad)++instance PrimMonad (DLListMonad s b) where+  type PrimState (DLListMonad s b) = s+  primitive = DLListMonad . primitive++instance MonadReader (DLList s b) (DLListMonad s b) where+  local f = DLListMonad . local f . runDLListMonad'+  ask = DLListMonad ask++-- | Runs a DLList Computation, starting with singleton values, crated+-- from the input vector.+runDLListMonad         :: V.Vector b -> (forall s. DLListMonad s b a) -> a+runDLListMonad vs comp = runST $ singletons vs >>= runReaderT (runDLListMonad' comp)++----------------------------------------++-- | Constructs a new DoublyLinkedList. Every element is its own singleton list+singletons    :: (PrimMonad m, s ~ PrimState m) => V.Vector b -> m (DLList s b)+singletons vs = DLList vs <$> MV.replicate (V.length vs) emptyCell++-- | Sets the DoublyLinkedList to the given List.+--+-- Indices that do not occur in the list are not touched.+writeList   :: NonEmpty Index -> DLListMonad s b ()+writeList h = do v <- asks llist+                 forM_ (withNeighs h) $ \(STR p i s) ->+                   modify v i $ \c -> c { prev = p , next = s }+  where+    withNeighs (x:|xs) = let l = x:xs+                         in zipWith3 STR (Nothing : map Just l) l (map Just xs ++ [Nothing])++----------------------------------------+-- * Queries++-- | Gets the value at Index i+valueAt    :: Index -> DLListMonad s b b+valueAt  i = asks ((V.! i) . values)++-- | Next element in the List+getNext   :: Index -> DLListMonad s b (Maybe Index)+getNext i = do v <- asks llist+               next <$> MV.read v i++-- | Previous Element in the List+getPrev   :: Index -> DLListMonad s b (Maybe Index)+getPrev i = do v <- asks llist+               prev <$> MV.read v i++-- | Computes a maximal length list starting from the Given index+--+-- running time: \(O(k)\), where \(k\) is the length of the output list+toListFrom   :: Index -> DLListMonad s b (NonEmpty Index)+toListFrom i = (i :|) <$> iterateM getNext i++-- | Takes the current element and its k next's+toListFromK     :: Index -> Int -> DLListMonad s b (NonEmpty Index)+toListFromK i k = (i :|) <$> replicateM k getNext i++-- | Computes a maximal length list by walking backwards in the+-- DoublyLinkedList, starting from the Given index+--+-- running time: \(O(k)\), where \(k\) is the length of the output list+toListFromR :: Index -> DLListMonad s b (NonEmpty Index)+toListFromR i = (i :|) <$> iterateM getPrev i++-- | Takes the current element and its k prev's+toListFromRK     :: Index -> Int -> DLListMonad s b (NonEmpty Index)+toListFromRK i k = (i :|) <$> replicateM k getPrev i++-- | Computes a maximal length list that contains the element i.+--+-- running time: \(O(k)\), where \(k\) is the length of the output+-- list+toListContains   :: Index -> DLListMonad s b (NonEmpty Index)+toListContains i = f <$> toListFromR i <*> toListFrom i+  where+    f l r = NonEmpty.fromList $ reverse (NonEmpty.toList l) <> NonEmpty.tail r+++----------------------------------------+-- * Updates++-- | Inserts the second argument after the first one into the linked list+insertAfter     :: Index -> Index -> DLListMonad s b ()+insertAfter i j = do v  <- asks llist+                     mr <- getNext i+                     modify  v i  $ \c -> c { next = Just j }+                     modify  v j  $ \c -> c { prev = Just i , next = mr }+                     mModify v mr $ \c -> c { prev = Just j }++-- | Inserts the second argument before the first one into the linked list+insertBefore     :: Index -> Index -> DLListMonad s b ()+insertBefore i h = do v <- asks llist+                      ml <- getPrev i+                      mModify v ml $ \c -> c { next = Just h }+                      modify  v h  $ \c -> c { prev = ml , next = Just i }+                      modify  v i  $ \c -> c { prev = Just h }++-- | Deletes the element from the linked list. This element thus+-- essentially becomes a singleton list. Returns the pair of indices+-- that now have become neighbours (i.e. the predecessor and successor+-- of j just before we deleted j).+delete   :: Index -> DLListMonad s b (Maybe Index, Maybe Index)+delete j = do v <- asks llist+              ml <- getPrev j+              mr <- getNext j+              modify  v j  $ \c -> c { prev = Nothing, next = Nothing }+              mModify v ml $ \c -> c { next = mr }+              mModify v mr $ \c -> c { prev = ml }+              pure (ml,mr)+++++----------------------------------------+-- * Helper functions++-- | Applies the action at most n times.+replicateM     :: Monad m => Int -> (a -> m (Maybe a)) -> a -> m [a]+replicateM n f = go n+  where+    go 0 _ = pure []+    go k x = f x >>= \case+               Nothing -> pure []+               Just y  -> (y:) <$> go (k-1) y++iterateM  :: Monad m => (a -> m (Maybe a)) -> a -> m [a]+iterateM f = go+  where+    go x = f x >>= \case+             Nothing -> pure []+             Just y  -> (y:) <$> go y++mModify   :: PrimMonad m => MV.MVector (PrimState m) a -> Maybe Int -> (a -> a) -> m ()+mModify v mi f = case mi of+                   Nothing -> pure ()+                   Just i  -> modify v i f++modify        :: PrimMonad m => MV.MVector (PrimState m) a -> Int -> (a -> a) -> m ()+modify v i f = MV.modify v f i+++--------------------------------------------------------------------------------++-- | For debugging purposes, dump the values and the cells+dump :: DLListMonad s a (V.Vector a, V.Vector Cell)+dump = do DLList v cs <- ask+          cs' <- V.freeze cs+          pure (v,cs')
+ src/Data/IndexedDoublyLinkedList/Bare.hs view
@@ -0,0 +1,197 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.IndexedDoublyLinkedList.Bare+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.IndexedDoublyLinkedList.Bare(+    IDLList(..)+  , Cell(..), emptyCell+  , IDLListMonad, runIDLListMonad+  , Index++  , singletons+  , writeList+  , getNext, getPrev+  , toListFrom, toListFromR, toListContains+  , toListFromK, toListFromRK+  , insertAfter, insertBefore+  , delete+  , dump+  ) where++import           Control.Monad.Primitive (PrimMonad(..))+import           Control.Monad.Reader (ReaderT, runReaderT)+import           Control.Monad.Reader.Class+import           Control.Monad.ST+import           Data.Foldable (forM_)+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.Util+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV++--------------------------------------------------------------------------------++-- | Cell indices. Must be non-negative.+type Index = Int++-- | Cells in the Linked List+data Cell = Cell { prev :: !(Maybe Index)+                 , next :: !(Maybe Index)+                 } deriving (Show,Eq)++-- | Empty cell with no next or prev cells.+emptyCell :: Cell+emptyCell = Cell Nothing Nothing++-- | Doubly linked list implemented by a mutable vector. So actually+-- this data type can represent a collection of Linked Lists that can+-- efficiently be concatenated and split.+--+-- Supports O(1) indexing, and O(1) insertions, deletions+newtype IDLList s = IDLList { llist  :: MV.MVector s Cell }++--------------------------------------------------------------------------------++-- | Monad in which we can use the IndexedDoublyLinkedList.+newtype IDLListMonad s a = IDLListMonad { runIDLListMonad' :: ReaderT (IDLList s) (ST s) a }+                        deriving (Functor,Applicative,Monad)++instance PrimMonad (IDLListMonad s) where+  type PrimState (IDLListMonad s) = s+  primitive = IDLListMonad . primitive++instance MonadReader (IDLList s) (IDLListMonad s) where+  local f = IDLListMonad . local f . runIDLListMonad'+  ask = IDLListMonad ask++-- | Runs a DLList Computation, starting with n singleton values+runIDLListMonad        :: Int -> (forall s. IDLListMonad s a) -> a+runIDLListMonad n comp = runST $ singletons n >>= runReaderT (runIDLListMonad' comp)++----------------------------------------++-- | Constructs a new DoublyLinkedList, of size at most n+singletons   :: (PrimMonad m, s ~ PrimState m) => Int -> m (IDLList s)+singletons n = IDLList <$> MV.replicate n emptyCell++-- | Sets the DoublyLinkedList to the given List.+--+-- Indices that do not occur in the list are not touched.+writeList   :: NonEmpty Index -> IDLListMonad s ()+writeList h = do v <- asks llist+                 forM_ (withNeighs h) $ \(STR p i s) ->+                   modify v i $ \c -> c { prev = p , next = s }+  where+    withNeighs (x:|xs) = let l = x:xs+                         in zipWith3 STR (Nothing : map Just l) l (map Just xs ++ [Nothing])++----------------------------------------+-- * Queries++-- | Next element in the List+getNext   :: Index -> IDLListMonad s (Maybe Index)+getNext i = do v <- asks llist+               next <$> MV.read v i++-- | Previous Element in the List+getPrev   :: Index -> IDLListMonad s (Maybe Index)+getPrev i = do v <- asks llist+               prev <$> MV.read v i++-- | Computes a maximal length list starting from the Given index+--+-- running time: \(O(k)\), where \(k\) is the length of the output list+toListFrom   :: Index -> IDLListMonad s (NonEmpty Index)+toListFrom i = (i :|) <$> iterateM getNext i++-- | Takes the current element and its k next's+toListFromK     :: Index -> Int -> IDLListMonad s (NonEmpty Index)+toListFromK i k = (i :|) <$> replicateM k getNext i++-- | Computes a maximal length list by walking backwards in the+-- DoublyLinkedList, starting from the Given index+--+-- running time: \(O(k)\), where \(k\) is the length of the output list+toListFromR :: Index -> IDLListMonad s (NonEmpty Index)+toListFromR i = (i :|) <$> iterateM getPrev i++-- | Takes the current element and its k prev's+toListFromRK     :: Index -> Int -> IDLListMonad s (NonEmpty Index)+toListFromRK i k = (i :|) <$> replicateM k getPrev i++-- | Computes a maximal length list that contains the element i.+--+-- running time: \(O(k)\), where \(k\) is the length of the output+-- list+toListContains   :: Index -> IDLListMonad s (NonEmpty Index)+toListContains i = f <$> toListFromR i <*> toListFrom i+  where+    f l r = NonEmpty.fromList $ reverse (NonEmpty.toList l) <> NonEmpty.tail r+++----------------------------------------+-- * Updates++-- | Inserts the second argument after the first one into the linked list+insertAfter     :: Index -> Index -> IDLListMonad s ()+insertAfter i j = do v  <- asks llist+                     mr <- getNext i+                     modify  v i  $ \c -> c { next = Just j }+                     modify  v j  $ \c -> c { prev = Just i , next = mr }+                     mModify v mr $ \c -> c { prev = Just j }++-- | Inserts the second argument before the first one into the linked list+insertBefore     :: Index -> Index -> IDLListMonad s ()+insertBefore i h = do v <- asks llist+                      ml <- getPrev i+                      mModify v ml $ \c -> c { next = Just h }+                      modify  v h  $ \c -> c { prev = ml , next = Just i }+                      modify  v i  $ \c -> c { prev = Just h }++-- | Deletes the element from the linked list. This element thus+-- essentially becomes a singleton list.+delete   :: Index -> IDLListMonad s ()+delete j = do v <- asks llist+              ml <- getPrev j+              mr <- getNext j+              modify  v j  $ \c -> c { prev = Nothing, next = Nothing }+              mModify v ml $ \c -> c { next = mr }+              mModify v mr $ \c -> c { prev = ml }++----------------------------------------+-- * Helper functions++-- | Applies the action at most n times.+replicateM     :: Monad m => Int -> (a -> m (Maybe a)) -> a -> m [a]+replicateM n f = go n+  where+    go 0 _ = pure []+    go k x = f x >>= \case+               Nothing -> pure []+               Just y  -> (y:) <$> go (k-1) y++iterateM  :: Monad m => (a -> m (Maybe a)) -> a -> m [a]+iterateM f = go+  where+    go x = f x >>= \case+             Nothing -> pure []+             Just y  -> (y:) <$> go y++mModify   :: PrimMonad m => MV.MVector (PrimState m) a -> Maybe Int -> (a -> a) -> m ()+mModify v mi f = case mi of+                   Nothing -> pure ()+                   Just i  -> modify v i f++modify        :: PrimMonad m => MV.MVector (PrimState m) a -> Int -> (a -> a) -> m ()+modify v i f = MV.modify v f i+++--------------------------------------------------------------------------------++-- | For debugging purposes, dump the values and the cells+dump :: IDLListMonad s (V.Vector Cell)+dump = do IDLList cs <- ask+          V.freeze cs
src/Data/Intersection.hs view
@@ -35,16 +35,19 @@ coRec :: (a ∈ as) => a -> CoRec Identity as coRec = CoRec . Identity -class IsIntersectableWith g h where-  intersect :: g -> h -> Intersection g h-+class HasIntersectionWith g h where   -- | g `intersects` h  <=> The intersection of g and h is non-empty.   --   -- The default implementation computes the intersection of g and h,   -- and uses nonEmptyIntersection to determine if the intersection is   -- non-empty.   intersects :: g -> h -> Bool+  default intersects :: IsIntersectableWith g h => g -> h -> Bool   g `intersects` h = nonEmptyIntersection (Identity g) (Identity h) $ g `intersect` h++-- | Class relationship between intersectable geometric objects.+class HasIntersectionWith g h => IsIntersectableWith g h where+  intersect :: g -> h -> Intersection g h    -- | Helper to implement `intersects`.   nonEmptyIntersection :: proxy g -> proxy h -> Intersection g h -> Bool
src/Data/LSeq.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE BangPatterns #-} -------------------------------------------------------------------------------- -- | -- Module      :  Data.LSeq@@ -8,7 +9,7 @@ -- Description :  Wrapper around Data.Sequence with type level length annotation. -- ---------------------------------------------------------------------------------module Data.LSeq( LSeq+module Data.LSeq( LSeq( EmptyL, (:<|), (:<<), (:|>) )                 , toSeq                 , empty                 , fromList@@ -17,7 +18,7 @@                  , (<|), (|>)                 , (><)-                , eval+                , eval, eval'                  , index                 , adjust@@ -26,39 +27,38 @@                 , take                 , drop                 , unstableSort, unstableSortBy-                , head, last+                , head, tail, last, init                 , append+                , reverse                  , ViewL(..)                 , viewl-                , pattern (:<|) -                , pattern (:<<)-                , pattern EmptyL-                 , ViewR(..)                 , viewr-                , pattern (:|>) +                , zipWith                  , promise                 , forceLSeq                 ) where  import           Control.DeepSeq-import           Control.Lens ((%~), (&), (<&>), (^?), bimap)+import           Control.Lens ((%~), (&), (<&>), (^?!), bimap) import           Control.Lens.At (Ixed(..), Index, IxValue) import           Data.Aeson+import           Data.Coerce(coerce) import qualified Data.Foldable as F+import           Data.Functor.Apply import qualified Data.List.NonEmpty as NonEmpty-import           Data.Maybe (fromJust) import           Data.Proxy import           Data.Semigroup.Foldable+import           Data.Semigroup.Traversable import qualified Data.Sequence as S import qualified Data.Traversable as Tr import           GHC.Generics (Generic) import           GHC.TypeLits-import           Prelude hiding (drop,take,head,last)+import           Prelude hiding (drop,take,head,last,tail,init,zipWith,reverse) import           Test.QuickCheck (Arbitrary(..),vector)  --------------------------------------------------------------------------------@@ -75,6 +75,7 @@                           deriving (Show,Read,Eq,Ord,Foldable,Functor,Traversable                                    ,Generic,NFData) +-- | \( O(1) \) Convert to a sequence by dropping the type-level size. toSeq          :: LSeq n a -> S.Seq a toSeq (LSeq s) = s @@ -103,108 +104,156 @@     | otherwise                 = pure s  instance (1 <= n) => Foldable1 (LSeq n)+instance (1 <= n) => Traversable1 (LSeq n) where+  traverse1 f (LSeq xs) = case runMaybeApply $ traverse (MaybeApply . Left . f) xs of+                            Left xs' -> LSeq <$> xs'+                            Right _  -> error "Data.LSeq.traverse1: impossible" +-- | \( O(1) \) The empty sequence. empty :: LSeq 0 a empty = LSeq S.empty +-- | \( O(1) \) Add an element to the left end of a sequence.+--   Mnemonic: a triangle with the single element at the pointy end. (<|) :: a -> LSeq n a -> LSeq (1 + n) a x <| xs = LSeq (x S.<| toSeq xs) +-- | \( O(1) \) Add an element to the right end of a sequence.+--   Mnemonic: a triangle with the single element at the pointy end. (|>)    :: LSeq n a -> a -> LSeq (1 + n) a xs |> x = LSeq (toSeq xs S.|> x)  infixr 5 <| infixl 5 |> +-- | \( O(log(min(n,m))) \) Concatenate two sequences. (><) :: LSeq n a -> LSeq m a -> LSeq (n + m) a xs >< ys = LSeq (toSeq xs <> toSeq ys)  infix 5 >< +-- | \( O(1) \) Prove a sequence has at least @n@ elements.+--+-- >>> eval @3 (fromList [1,2,3])+-- Just (LSeq (fromList [1,2,3]))+-- >>> eval @3 (fromList [1,2])+-- Nothing+-- >>> eval @3 (fromList [1..10])+-- Just (LSeq (fromList [1,2,3,4,5,6,7,8,9,10]))+eval :: forall n m a. KnownNat n => LSeq m a -> Maybe (LSeq n a)+eval = eval' (Proxy @n) -eval :: forall proxy n m a. KnownNat n => proxy n -> LSeq m a -> Maybe (LSeq n a)-eval n (LSeq xs)+-- | Implementatio nof eval' that takes an explicit proxy.+eval' :: forall proxy n m a. KnownNat n => proxy n -> LSeq m a -> Maybe (LSeq n a)+eval' n (LSeq xs)   | toInteger (S.length xs) >= natVal n = Just $ LSeq xs   | otherwise                           = Nothing  --- -- | Promises that the length of this LSeq is actually n. This is not -- checked. -- -- This function should be a noop-promise :: LSeq m a -> LSeq n a-promise = LSeq . toSeq-+promise :: forall n m a. LSeq m a -> LSeq n a+promise = coerce  -- | Forces the first n elements of the LSeq forceLSeq   :: KnownNat n => proxy n -> LSeq m a -> LSeq n a forceLSeq n = promise . go (fromInteger $ natVal n)   where     -- forces the Lseq for n' positions-    go      :: Int -> LSeq m a -> LSeq m a-    go n' s | n' <= l    = s-            | otherwise  = error msg+    go                    :: Int -> LSeq m a -> LSeq m a+    go !n' s | n' <= l    = s+             | otherwise  = error msg       where-        l   = S.length . S.take n' . toSeq $ s+        !l  = S.length . S.take n' . toSeq $ s         msg = "forceLSeq: too few elements. expected " <> show n' <> " but found " <> show l   -- | appends two sequences. -- append         :: LSeq n a -> LSeq m a -> LSeq (n + m) a-sa `append` sb = LSeq $ (toSeq sa) <> toSeq sb+sa `append` sb = LSeq $ toSeq sa <> toSeq sb  -------------------------------------------------------------------------------- --- | get the element with index i, counting from the left and starting at 0.--- O(log(min(i,n-i)))+-- | \( O(log(min(i,n-i))) \)+--   Get the element with index i, counting from the left and starting at 0. index     :: LSeq n a -> Int -> a-index s i = fromJust $ s^?ix i+index s i = s^?!ix i +-- | \( O(log(min(i,n−i))) \) Update the element at the specified position. If the+--   position is out of range, the original sequence is returned. adjust can lead+--   to poor performance and even memory leaks, because it does not force the new+--   value before installing it in the sequence. adjust' should usually be preferred. adjust       :: (a -> a) -> Int -> LSeq n a -> LSeq n a adjust f i s = s&ix i %~ f -+-- | \( O(n) \) The partition function takes a predicate p and a sequence xs and+--   returns sequences of those elements which do and do not satisfy the predicate. partition   :: (a -> Bool) -> LSeq n a -> (LSeq 0 a, LSeq 0 a) partition p = bimap LSeq LSeq . S.partition p . toSeq +-- | A generalization of 'fmap', 'mapWithIndex' takes a mapping+-- function that also depends on the element's index, and applies it to every+-- element in the sequence. mapWithIndex   :: (Int -> a -> b) -> LSeq n a -> LSeq n b mapWithIndex f = wrapUnsafe (S.mapWithIndex f) +-- | \( O(\log(\min(i,n-i))) \). The first @i@ elements of a sequence.+-- If @i@ is negative, @'take' i s@ yields the empty sequence.+-- If the sequence contains fewer than @i@ elements, the whole sequence+-- is returned. take   :: Int -> LSeq n a -> LSeq 0 a take i = wrapUnsafe (S.take i) +-- | \( O(\log(\min(i,n-i))) \). Elements of a sequence after the first @i@.+-- If @i@ is negative, @'drop' i s@ yields the whole sequence.+-- If the sequence contains fewer than @i@ elements, the empty sequence+-- is returned. drop   :: Int -> LSeq n a -> LSeq 0 a drop i = wrapUnsafe (S.drop i) -+-- | \( O(n \log n) \).  A generalization of 'unstableSort', 'unstableSortBy'+-- takes an arbitrary comparator and sorts the specified sequence.+-- The sort is not stable.  This algorithm is frequently faster and+-- uses less memory than 'Data.Sequence.sortBy'. unstableSortBy   :: (a -> a -> Ordering) -> LSeq n a -> LSeq n a unstableSortBy f = wrapUnsafe (S.unstableSortBy f) +-- | \( O(n \log n) \).  'unstableSort' sorts the specified 'LSeq' by+-- the natural ordering of its elements, but the sort is not stable.+-- This algorithm is frequently faster and uses less memory than 'Data.Sequence.sort'. unstableSort :: Ord a => LSeq n a -> LSeq n a-unstableSort = wrapUnsafe (S.unstableSort)+unstableSort = wrapUnsafe S.unstableSort   wrapUnsafe :: (S.Seq a -> S.Seq b) -> LSeq n a -> LSeq m b wrapUnsafe f = LSeq . f . toSeq +-- | Reverses the sequence.+reverse :: LSeq n a -> LSeq n a+reverse = wrapUnsafe S.reverse++ -------------------------------------------------------------------------------- +-- | \( O(1) \). Create an l-sequence from a sequence of elements. fromSeq :: S.Seq a -> LSeq 0 a fromSeq = LSeq +-- | \( O(n) \). Create an l-sequence from a finite list of elements. fromList :: Foldable f => f a -> LSeq 0 a fromList = LSeq . S.fromList . F.toList +-- | \( O(n) \). Create an l-sequence from a non-empty list. fromNonEmpty :: NonEmpty.NonEmpty a -> LSeq 1 a fromNonEmpty = LSeq . S.fromList . F.toList   -------------------------------------------------------------------------------- +-- | View of the left end of a sequence. data ViewL n a where   (:<) :: a -> LSeq n a -> ViewL (1 + n) a @@ -220,12 +269,21 @@   foldMap = Tr.foldMapDefault instance Traversable (ViewL n) where   traverse f (x :< xs) = (:<) <$> f x <*> traverse f xs+instance (1 <= n) => Foldable1 (ViewL n)+instance (1 <= n) => Traversable1 (ViewL n) where+  traverse1 f (a :< LSeq as) = (\(b :< bs) -> b :< promise bs) <$> go a as+    where+      go x = \case+        S.Empty       -> (:< empty) <$> f x+        (y S.:<| ys) -> (\x' (y' :< ys') -> x' :< promise @0 (y' :<| ys'))+                        <$> f x <.> go y ys+ instance Eq a => Eq (ViewL n a) where   s == s' = F.toList s == F.toList s' instance Ord a => Ord (ViewL n a) where   s `compare` s' = F.toList s `compare` F.toList s' -+-- | \( O(1) )\. Analyse the left end of a sequence. viewl :: LSeq (1 + n) a -> ViewL (1 + n) a viewl xs = let ~(x S.:< ys) = S.viewl $ toSeq xs in x :< LSeq ys @@ -234,6 +292,8 @@  infixr 5 :<| +-- | A bidirectional pattern synonym viewing the front of a non-empty+-- sequence. pattern (:<|)    :: a -> LSeq n a -> LSeq (1 + n) a pattern x :<| xs <- (viewl' -> (x,xs)) -- we need the coerce unfortunately   where@@ -244,9 +304,12 @@  infixr 5 :<< +-- | A unidirectional pattern synonym viewing the front of a non-empty+-- sequence. pattern (:<<)    :: a -> LSeq 0 a -> LSeq n a pattern x :<< xs <- (viewLSeq -> Just (x,xs)) +-- | The empty sequence. pattern EmptyL   :: LSeq n a pattern EmptyL   <- (viewLSeq -> Nothing) @@ -258,6 +321,7 @@  -------------------------------------------------------------------------------- +-- | View of the right end of a sequence. data ViewR n a where   (:>) :: LSeq n a -> a -> ViewR (1 + n) a @@ -278,6 +342,7 @@ instance Ord a => Ord (ViewR n a) where   s `compare` s' = F.toList s `compare` F.toList s' +-- | \( O(1) \). Analyse the right end of a sequence. viewr    :: LSeq (1 + n) a -> ViewR (1 + n) a viewr xs = let ~(ys S.:> x) = S.viewr $ toSeq xs in LSeq ys :> x @@ -286,6 +351,8 @@  infixl 5 :|> +-- | A bidirectional pattern synonym viewing the rear of a non-empty+-- sequence. pattern (:|>)    :: forall n a. LSeq n a -> a -> LSeq (1 + n) a pattern xs :|> x <- (viewr' -> (xs,x))   where@@ -301,6 +368,12 @@ head           :: LSeq (1 + n) a -> a head (x :<| _) = x +-- | Get the LSeq without its first element+-- -- >>> head $ forceLSeq (Proxy :: Proxy 3) $ fromList [1,2,3]+-- LSeq (fromList [2,3])+tail           :: LSeq (1 + n) a -> LSeq n a+tail (_ :<| s) = s+ -- s = let (x :< _) = viewl s in x  -- | Get the last element of the LSeq@@ -310,6 +383,14 @@ last           :: LSeq (1 + n) a -> a last (_ :|> x) = x ++-- | The sequence without its last element+--+-- >>> init $ forceLSeq (Proxy :: Proxy 3) $ fromList [1,2,3]+-- LSeq (fromList [1,2])+init           :: LSeq (1 + n) a -> LSeq n a+init (s :|> _) = s+ -- testL = (eval (Proxy :: Proxy 2) $ fromList [1..5])  -- testL' :: LSeq 2 Integer@@ -317,3 +398,10 @@  -- test            :: Show a => LSeq (1 + n) a -> String -- test (x :<| xs) = show x ++ show xs+++--------------------------------------------------------------------------------++-- | Zips two equal length LSeqs+zipWith         :: (a -> b -> c) -> LSeq n a -> LSeq n b -> LSeq n c+zipWith f sa sb = LSeq $ S.zipWith f (toSeq sa) (toSeq sb)
+ src/Data/List/Alternating.hs view
@@ -0,0 +1,93 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.List.Alternating+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.List.Alternating(+    Alternating(..)+  , withNeighbours+  , mergeAlternating+  , insertBreakPoints+  , reverse+  ) where++import Prelude hiding (reverse)+import Control.Lens+import Data.Bifoldable+import Data.Bitraversable+import Data.Ext+import qualified Data.List as List++--------------------------------------------------------------------------------++-- | A (non-empty) alternating list of @a@\'s and @b@\'s+data Alternating a b = Alternating a [b :+ a] deriving (Show,Eq,Ord)++instance Bifunctor Alternating where+  bimap = bimapDefault+instance Bifoldable Alternating where+  bifoldMap = bifoldMapDefault+instance Bitraversable Alternating where+  bitraverse f g (Alternating a xs) = Alternating <$> f a <*> traverse (bitraverse g f) xs+++-- | Computes a b with all its neighbours+--+-- >>> withNeighbours (Alternating 0 ['a' :+ 1, 'b' :+ 2, 'c' :+ 3])+-- [(0,'a' :+ 1),(1,'b' :+ 2),(2,'c' :+ 3)]+withNeighbours                     :: Alternating a b -> [(a,b :+ a)]+withNeighbours (Alternating a0 xs) = let as = a0 : map (^.extra) xs+                                     in zip as xs++++-- | Generic merging scheme that merges two Alternatings and applies+-- the function '@f@', with the current/new value at every event. So+-- note that if the alternating consists of 'Alternating a0 [t1 :++-- a1]' then the function is applied to a1, not to a0 (i.e. every+-- value ai is considered alive on the interval [ti,t(i+1))+--+-- >>> let odds  = Alternating "a" [3 :+ "c", 5 :+ "e", 7 :+ "g"]+-- >>> let evens = Alternating "b" [4 :+ "d", 6 :+ "f", 8 :+ "h"]+-- >>> mergeAlternating (\_ a b -> a <> b) odds evens+-- [3 :+ "cb",4 :+ "cd",5 :+ "ed",6 :+ "ef",7 :+ "gf",8 :+ "gh"]+-- >>> mergeAlternating (\t a b -> if t `mod` 2 == 0 then a else b) odds evens+-- [3 :+ "b",4 :+ "c",5 :+ "d",6 :+ "e",7 :+ "f",8 :+ "g"]+-- >>> mergeAlternating (\_ a b -> a <> b) odds (Alternating "b" [0 :+ "d", 5 :+ "e", 8 :+ "h"])+-- [0 :+ "ad",3 :+ "cd",5 :+ "ee",7 :+ "ge",8 :+ "gh"]+mergeAlternating                         :: Ord t+                                         => (t -> a -> b -> c)+                                         -> Alternating a t -> Alternating b t -> [t :+ c]+mergeAlternating f (Alternating a00 as0)+                   (Alternating b00 bs0) = go a00 b00 as0 bs0+  where+    go a  _  []                bs                 = map (\(t :+ b) -> t :+ f t a b) bs+    go _  b  as                []                 = map (\(t :+ a) -> t :+ f t a b) as+    go a0 b0 as@((t :+ a):as') bs@((t' :+ b):bs') = case t `compare` t' of+                                                      LT -> (t  :+ f t  a  b0) : go a  b0 as' bs+                                                      EQ -> (t  :+ f t  a  b)  : go a  b  as' bs'+                                                      GT -> (t' :+ f t' a0 b)  : go a0 b  as  bs'+++-- | Adds additional t-values in the alternating, (in sorted order). I.e. if we insert a+-- "breakpoint" at time t the current '@a@' value is used at that time.+--+-- >>> insertBreakPoints [0,2,4,6,8,10] $ Alternating "a" [3 :+ "c", 5 :+ "e", 7 :+ "g"]+-- Alternating "a" [0 :+ "a",2 :+ "a",3 :+ "c",4 :+ "c",5 :+ "e",6 :+ "e",7 :+ "g",8 :+ "g",10 :+ "g"]+insertBreakPoints                         :: Ord t => [t] -> Alternating a t -> Alternating a t+insertBreakPoints ts a@(Alternating a0 _) =+  Alternating a0 $ mergeAlternating (\_ _ a' -> a') (Alternating undefined (ext <$> ts)) a+++-- | Reverses an alternating list.+--+-- >>> reverse $ Alternating "a" [3 :+ "c", 5 :+ "e", 7 :+ "g"]+-- Alternating "g" [7 :+ "e",5 :+ "c",3 :+ "a"]+reverse                      :: Alternating a b -> Alternating a b+reverse p@(Alternating s xs) = case xs of+    []             -> p+    ((e1 :+ _):tl) -> let ys = (e1 :+ s) : List.zipWith (\(_ :+ v) (e :+ _) -> e :+ v) xs tl+                          t  = last xs ^. extra+                      in Alternating t (List.reverse ys)
+ src/Data/List/Set.hs view
@@ -0,0 +1,70 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.List.Set+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.List.Set( Set, singleton+                    , insert, delete+                    , union, intersection, difference+                    , fromList, insertAll+                    ) where++import qualified Data.List as List++--------------------------------------------------------------------------------++-- | A Set of @a@\'s, implemented using a simple list. The only+-- advantage of this implementation over 'Data.Set' from containers is+-- that most operations require only @'Eq a'@ rather than @'Ord a'@.+newtype Set a = Set { toList :: [a] }+              deriving (Show,Read,Functor,Foldable,Traversable)++instance Eq a => Eq (Set a) where+  (Set xs) == (Set ys) = all (`elem` ys) xs &&  all (`elem` xs) ys+++instance Eq a => Semigroup (Set a) where+  (Set xs) <> s = insertAll xs s++instance Eq a => Monoid (Set a) where+  mempty = Set []++-- | Creates a singleton set.+singleton   :: a -> Set a+singleton x = Set [x]++-- | \(O(n)\) Inserts an element in the set+insert                           :: Eq a => a -> Set a -> Set a+insert x s@(Set xs) | x `elem` s = s+                    | otherwise  = Set (x:xs)++-- | \( O(n^2) \) Insert an element in a set.+insertAll      :: Eq a => [a] -> Set a -> Set a+insertAll xs s = List.foldl' (flip insert) s xs++-- | \( O(n^2) \) Create a set from a finite list of elements.+fromList :: Eq a => [a] -> Set a+fromList = flip insertAll mempty++-- | \(O(n)\) Deletes an element from the set+delete            :: Eq a => a -> Set a -> Set a+delete x (Set xs) = Set $ go xs+  where+    go = \case+      [] -> []+      (y:ys) | x == y    -> ys -- found the element, no need to continue looking+             | otherwise -> y:go ys++-- | \(O(n^2)\) Computes the union of two sets+union :: Eq a => Set a -> Set a -> Set a+union = (<>)++-- | \(O(n^2)\) Computes the intersection of two sets+intersection                     :: Eq a => Set a -> Set a -> Set a+(Set xs) `intersection` (Set ys) = Set (xs `List.intersect` ys)++-- | \(O(n^2)\) Computes the difference of two sets+difference :: Eq a => Set a -> Set a -> Set a+(Set xs) `difference` (Set ys) = Set $ xs List.\\ ys
+ src/Data/List/Util.hs view
@@ -0,0 +1,144 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.List.Util+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.List.Util where++import           Data.Bifunctor+import           Data.Ext+import qualified Data.Foldable as F+import qualified Data.List as List+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.List.Zipper (allNonEmptyNexts, extractNext)+import qualified Data.List.Zipper as Zipper+import           Data.Maybe+import           Data.Ord (comparing)++--------------------------------------------------------------------------------++-- | Given an input list, computes all lists in which just one element is missing.+--+-- >>> mapM_ print $ leaveOutOne [1..5]+-- (1,[2,3,4,5])+-- (2,[1,3,4,5])+-- (3,[1,2,4,5])+-- (4,[1,2,3,5])+-- (5,[1,2,3,4])+-- >>> leaveOutOne []+-- []+-- >>> leaveOutOne [1]+-- [(1,[])]+leaveOutOne    :: [a] -> [(a,[a])]+leaveOutOne xs = second F.toList . fromJust . extractNext+              <$> allNonEmptyNexts (Zipper.fromList xs)+++--------------------------------------------------------------------------------+-- * Improved functions for minima and maxima++-- | Safe variant of Prelude.minimum.+--+-- >>> minimum1 [] :: Maybe ()+-- Nothing+-- >>> minimum1 [1,2,3]+-- Just 1+minimum1 :: Ord a => [a] -> Maybe a+minimum1 = minimum1By compare++-- | Safe variant of Prelude.maximum.+--+-- >>> maximum1 [] :: Maybe ()+-- Nothing+-- >>> maximum1 [1,2,3]+-- Just 3+maximum1 :: Ord a => [a] -> Maybe a+maximum1 = minimum1By (flip compare)++-- | Total variant of Data.List.minimumBy.+--+-- >>> minimum1By (comparing abs) [] :: Maybe Int+-- Nothing+-- >>> minimum1By (comparing abs) [1,-2,3]+-- Just 1+minimum1By     :: (a -> a -> Ordering) -> [a] -> Maybe a+minimum1By cmp = \case+  [] -> Nothing+  xs -> Just $ List.minimumBy cmp xs++-- | Computes all minima by comparing some property.+--+-- >>> minimaOn (max 2) [1,2,3,4,5,-1]+-- [-1,2,1]+minimaOn   :: Ord b => (a -> b) -> [a] -> [a]+minimaOn f = minimaBy (comparing f)++-- | Computes all minima.+--+-- >>> minimaBy (comparing abs) [1,2,3,2,1,-1]+-- [-1,1,1]+minimaBy     :: (a -> a -> Ordering) -> [a] -> [a]+minimaBy cmp = \case+  []     -> []+  (x:xs) -> NonEmpty.toList $ List.foldl' (\mins@(m:|_) y -> case m `cmp` y of+                                                               LT -> mins+                                                               EQ -> y NonEmpty.<| mins+                                                               GT -> y:|[]+                                          ) (x:|[]) xs++-- | extracts all minima from the list. The result consists of the+-- list of minima, and all remaining points. Both lists are returned+-- in the order in which they occur in the input.+--+-- >>> extractMinimaBy compare [1,2,3,0,1,2,3,0,1,2,0,2]+-- [0,0,0] :+ [2,3,1,2,3,1,2,1,2]+extractMinimaBy     :: (a -> a -> Ordering) -> [a] -> [a] :+ [a]+extractMinimaBy cmp = \case+  []     -> [] :+ []+  (x:xs) -> first NonEmpty.toList $ foldr (\y (mins@(m:|_) :+ rest) ->+                                             case m `cmp` y of+                                               LT -> mins :+ y:rest+                                               EQ -> (y NonEmpty.<| mins) :+ rest+                                               GT -> (y:|[]) :+ NonEmpty.toList mins <> rest+                                          ) ((x:|[]) :+ []) xs+  -- TODO: This is actually a good scenario for testing how much slower :+ is compared+  -- to doing nothing. i..e compare minimaBy and extractMinimaBy+  -- note that I'm using foldr here, and foldl' before+++--------------------------------------------------------------------------------+-- * Partitioning and Grouping++-- | Given a function f, partitions the list into three lists+-- (lts,eqs,gts) such that:+--+-- - f x == LT for all x in lts+-- - f x == EQ for all x in eqs+-- - f x == gt for all x in gts+--+-- >>> partition3 (compare 4) [0,1,2,2,3,4,5,5,6,6,7,7,7,7,7,8]+-- ([5,5,6,6,7,7,7,7,7,8],[4],[0,1,2,2,3])+--+partition3   :: Foldable f => (a -> Ordering) -> f a -> ([a],[a],[a])+partition3 f = foldr g ([],[],[])+  where+    g x (lts,eqs,gts) = case f x of+                          LT -> (x:lts,   eqs,  gts)+                          EQ -> (  lts, x:eqs,  gts)+                          GT -> (  lts,   eqs,x:gts)++-- | A version of groupBy that uses the given Ordering to group+-- consecutive Equal items+--+-- >>> groupBy' compare [0,1,2,2,3,4,5,5,6,6,7,7,7,7,7,8]+-- [0 :| [],1 :| [],2 :| [2],3 :| [],4 :| [],5 :| [5],6 :| [6],7 :| [7,7,7,7],8 :| []]+groupBy'     :: (a -> a -> Ordering) -> [a] -> [NonEmpty a]+groupBy' cmp = go+  where+    go = \case+      []       -> []+      (x:xs)   -> let (pref,rest) = List.span (\y -> x `cmp` y == EQ) xs+                  in (x :| pref) : go rest
+ src/Data/List/Zipper.hs view
@@ -0,0 +1,79 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.List.Zipper+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.List.Zipper where++import qualified Data.List as List++--------------------------------------------------------------------------------++-- | Simple Zipper for Lists.+data Zipper a = Zipper [a] [a] deriving (Show,Eq,Functor)++instance Foldable Zipper where+  -- Folds like it it is a normal list+  foldMap f (Zipper ls rs) = foldMap f (reverse ls) <> foldMap f rs+++-- | Construct a Zipper from a list+--+-- running time: \(O(1)\)+fromList :: [a] -> Zipper a+fromList = Zipper []++-- | Go to the Next Element+--+-- running time: \(O(1)\)+goNext                :: Zipper a -> Maybe (Zipper a)+goNext (Zipper xs ys) = case ys of+                          []    -> Nothing+                          x:ys' -> Just $ Zipper (x:xs) ys'++-- | Go to the previous Element+--+-- running time: \(O(1)\)+goPrev                :: Zipper a -> Maybe (Zipper a)+goPrev (Zipper xs ys) = case xs of+                          []    -> Nothing+                          x:xs' -> Just $ Zipper xs' (x:ys)++-- | Computes all nexts, even one that has no elements initially or at+-- the end.+--+-- >>> mapM_ print $ allNexts $ fromList [1..5]+-- Zipper [] [1,2,3,4,5]+-- Zipper [1] [2,3,4,5]+-- Zipper [2,1] [3,4,5]+-- Zipper [3,2,1] [4,5]+-- Zipper [4,3,2,1] [5]+-- Zipper [5,4,3,2,1] []+allNexts :: Zipper a -> [Zipper a]+allNexts = List.unfoldr (fmap (\z -> (z,goNext z))) . Just++-- | Returns the next element, and the zipper without it+extractNext                :: Zipper a -> Maybe (a, Zipper a)+extractNext (Zipper xs ys) = case ys of+                               []      -> Nothing+                               (y:ys') -> Just (y,Zipper xs ys')+++-- | Drops the next element in the zipper.+--+-- running time: \(O(1)\)+dropNext :: Zipper a -> Maybe (Zipper a)+dropNext = fmap snd . extractNext++-- | Computes all list that still have next elements.+--+-- >>> mapM_ print $ allNonEmptyNexts $ fromList [1..5]+-- Zipper [] [1,2,3,4,5]+-- Zipper [1] [2,3,4,5]+-- Zipper [2,1] [3,4,5]+-- Zipper [3,2,1] [4,5]+-- Zipper [4,3,2,1] [5]+allNonEmptyNexts :: Zipper a -> [Zipper a]+allNonEmptyNexts = List.unfoldr (\z -> (z,) <$> goNext z)
+ src/Data/Measured.hs view
@@ -0,0 +1,11 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Measured+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.Measured( module Data.Measured.Class+                    ) where++import Data.Measured.Class
+ src/Data/Measured/Class.hs view
@@ -0,0 +1,21 @@+{-# Language FunctionalDependencies #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Measured.Class+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.Measured.Class where++-- | Things that can be measured.+class Semigroup v => Measured v a | a -> v where+  measure :: a -> v++-- | Things that can be inserted.+class Measured v a => CanInsert v a where+  insertA :: a -> v -> v++-- | Things that can be deleted.+class Measured v a => CanDelete v a where+  deleteA :: a -> v -> Maybe v
+ src/Data/Measured/Size.hs view
@@ -0,0 +1,48 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Measured.Size+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.Measured.Size where++import Control.DeepSeq+import Data.Measured.Class+import GHC.Generics (Generic)++--------------------------------------------------------------------------------++-- | Measured size. Always non-negative.+newtype Size = Size Word deriving (Show,Read,Eq,Num,Integral,Enum,Real,Ord,Generic,NFData)++instance Semigroup Size where+  x <> y = x + y++instance Monoid Size where+  mempty = Size 0++--------------------------------------------------------------------------------++-- | Newtype wrapper for things for which we can measure the size+newtype Elem a = Elem { _unElem :: a }+               deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)++instance Measured Size (Elem a) where+  measure _ = 1++--------------------------------------------------------------------------------++-- | Things that have a size+data Sized a = Sized {-# UNPACK #-} !Size a+             deriving (Show,Eq,Ord,Functor,Foldable,Traversable,Generic)+instance NFData a => NFData (Sized a)++instance Semigroup a => Semigroup (Sized a) where+  (Sized i a) <> (Sized j b) = Sized (i <> j) (a <> b)++instance Monoid a => Monoid (Sized a) where+  mempty = Sized mempty mempty++-- instance Semigroup a => Measured Size (Sized a) where+--   measure (Sized i _) = i
src/Data/OrdSeq.hs view
@@ -1,12 +1,41 @@-module Data.OrdSeq where+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.OrdSeq+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.OrdSeq+  ( OrdSeq+  , Compare+  , insertBy+  , insert+  , splitBy+  , splitOn+  , splitMonotonic+  , deleteAll+  , deleteAllBy+  , fromListBy+  , fromListByOrd+  , fromAscList+  , lookupBy+  , memberBy+  , mapMonotonic+  , viewl+  , viewr+  , minView+  , lookupMin+  , maxView+  , lookupMax+  ) where  -import           Control.Lens (bimap)-import qualified Data.FingerTree as FT+import           Control.Lens    (bimap) import           Data.FingerTree hiding (null, viewl, viewr)-import qualified Data.Foldable as F-import           Data.Maybe-import           Test.QuickCheck+import qualified Data.FingerTree as FT+import qualified Data.Foldable   as F+import           Data.Maybe      (fromJust, isJust, listToMaybe)+import           Test.QuickCheck (Arbitrary (arbitrary))  -------------------------------------------------------------------------------- @@ -28,15 +57,18 @@   -newtype Elem a = Elem { getElem :: a } deriving (Eq,Ord,Traversable,Foldable,Functor)+newtype Elem a = Elem a deriving (Eq,Ord,Traversable,Foldable,Functor)  instance Show a => Show (Elem a) where   show (Elem x) = "Elem " <> show x -+-- | Sequence of ordered elements. newtype OrdSeq a = OrdSeq { _asFingerTree :: FingerTree (Key a) (Elem a) }-                   deriving (Show,Eq)+                   deriving (Eq) +instance Show a => Show (OrdSeq a) where+  show s = "fromAscList " ++ show (F.toList s)+ instance Semigroup (OrdSeq a) where   (OrdSeq s) <> (OrdSeq t) = OrdSeq $ s `mappend` t @@ -57,7 +89,7 @@ instance Measured (Key a) (Elem a) where   measure (Elem x) = Key x -+-- | Signature for functions that give the ordering of two values. type Compare a = a -> a -> Ordering  -- | Insert into a monotone OrdSeq.@@ -76,6 +108,7 @@ insert :: Ord a => a -> OrdSeq a -> OrdSeq a insert = insertBy compare +-- | \( O(\log n) \). Delete all elements that compare as equal to @x@. deleteAllBy         :: Compare a -> a -> OrdSeq a -> OrdSeq a deleteAllBy cmp x s = l <> r   where@@ -93,18 +126,18 @@     (m',r) = split (\v -> liftCmp cmp v (Key x) == GT) m  +{- HLINT ignore splitOn -} -- | Given a monotonic function f that maps a to b, split the sequence s -- depending on the b values. I.e. the result (l,m,r) is such that--- * all (< x) . fmap f $ l--- * all (== x) . fmap f $ m--- * all (> x) . fmap f $ r ----- >>> splitOn id 3 $ fromAscList' [1..5]--- (OrdSeq {_asFingerTree = fromList [Elem 1,Elem 2]},OrdSeq {_asFingerTree = fromList [Elem 3]},OrdSeq {_asFingerTree = fromList [Elem 4,Elem 5]})--- >>> splitOn fst 2 $ fromAscList' [(0,"-"),(1,"A"),(2,"B"),(2,"C"),(3,"D"),(4,"E")]--- (OrdSeq {_asFingerTree = fromList [Elem (0,"-"),Elem (1,"A")]},OrdSeq {_asFingerTree = fromList [Elem (2,"B"),Elem (2,"C")]},OrdSeq {_asFingerTree = fromList [Elem (3,"D"),Elem (4,"E")]})+-- * @all (< x) . fmap f $ l@+-- * @all (== x) . fmap f $ m@+-- * @all (> x) . fmap f $ r@ ----- \(O(\log n)\)+-- >>> splitOn id 3 $ fromAscList [1..5]+-- (fromAscList [1,2],fromAscList [3],fromAscList [4,5])+-- >>> splitOn fst 2 $ fromAscList [(0,"-"),(1,"A"),(2,"B"),(2,"C"),(3,"D"),(4,"E")]+-- (fromAscList [(0,"-"),(1,"A")],fromAscList [(2,"B"),(2,"C")],fromAscList [(3,"D"),(4,"E")]) splitOn :: Ord b => (a -> b) -> b -> OrdSeq a -> (OrdSeq a, OrdSeq a, OrdSeq a) splitOn f x (OrdSeq s) = (OrdSeq l, OrdSeq m', OrdSeq r)   where@@ -119,7 +152,7 @@ splitMonotonic p = bimap OrdSeq OrdSeq . split (p . getKey) . _asFingerTree  --- Deletes all elements from the OrdDeq+-- | Deletes all elements from the OrdDeq -- -- \(O(n\log n)\) deleteAll :: Ord a => a -> OrdSeq a -> OrdSeq a@@ -136,58 +169,56 @@ fromListByOrd :: Ord a => [a] -> OrdSeq a fromListByOrd = fromListBy compare --- | O(n)-fromAscList' :: [a] -> OrdSeq a-fromAscList' = OrdSeq . fromList . fmap Elem+-- | \( O(n) \)+fromAscList :: [a] -> OrdSeq a+fromAscList = OrdSeq . fromList . fmap Elem   -- | \(O(\log n)\) lookupBy         :: Compare a -> a -> OrdSeq a -> Maybe a lookupBy cmp x s = let (_,m,_) = splitBy cmp x s in listToMaybe . F.toList $ m +-- | \(O(\log n)\). Queries for the existance of any elements that compare as equal to @x@. memberBy        :: Compare a -> a -> OrdSeq a -> Bool memberBy cmp x = isJust . lookupBy cmp x  --- | Fmap, assumes the order does not change--- O(n)+-- | \( O(n) \) Fmap, assumes the order does not change mapMonotonic   :: (a -> b) -> OrdSeq a -> OrdSeq b-mapMonotonic f = fromAscList' . map f . F.toList+mapMonotonic f = fromAscList . map f . F.toList  --- | Gets the first element from the sequence--- \(O(1)\)+-- | \(O(1)\) Gets the first element from the sequence viewl :: OrdSeq a -> ViewL OrdSeq a viewl = f . FT.viewl . _asFingerTree   where-    f EmptyL         = EmptyL-    f (Elem x :< s)  = x :< OrdSeq s+    f EmptyL        = EmptyL+    f (Elem x :< s) = x :< OrdSeq s --- Last element--- \(O(1)\)+-- | \(O(1)\) Gets the last element from the sequence viewr :: OrdSeq a -> ViewR OrdSeq a viewr = f . FT.viewr . _asFingerTree   where-    f EmptyR         = EmptyR-    f (s :> Elem x)  = OrdSeq s :> x+    f EmptyR        = EmptyR+    f (s :> Elem x) = OrdSeq s :> x  --- \(O(1)\)+-- | \(O(1)\) minView   :: OrdSeq a -> Maybe (a, OrdSeq a) minView s = case viewl s of               EmptyL   -> Nothing               (x :< t) -> Just (x,t) --- \(O(1)\)+-- | \(O(1)\) lookupMin :: OrdSeq a -> Maybe a lookupMin = fmap fst . minView --- \(O(1)\)+-- | \(O(1)\) maxView   :: OrdSeq a -> Maybe (a, OrdSeq a) maxView s = case viewr s of               EmptyR   -> Nothing               (t :> x) -> Just (x,t) --- \(O(1)\)+-- | \(O(1)\) lookupMax :: OrdSeq a -> Maybe a lookupMax = fmap fst . maxView
src/Data/PlanarGraph.hs view
@@ -1,6 +1,4 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-} -------------------------------------------------------------------------------- -- | -- Module      :  Data.PlanarGraph@@ -47,6 +45,7 @@                        , tailOf, headOf, endPoints                        , incidentEdges, incomingEdges, outgoingEdges, neighboursOf                        , nextIncidentEdge, prevIncidentEdge+                       , nextIncidentEdgeFrom, prevIncidentEdgeFrom                         -- * Associated Data @@ -71,10 +70,12 @@  -------------------------------------------------------------------------------- -- $setup+-- >>> import qualified Data.Vector as V+-- >>> import Control.Lens -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -91,7 +92,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -99,8 +103,6 @@ -- arrows are just to indicate what the Positive direction of the darts is. -- -- ![myGraph](docs/Data/PlanarGraph/testG.png)--   --------------------------------------------------------------------------------
src/Data/PlanarGraph/AdjRep.hs view
@@ -11,16 +11,17 @@ -------------------------------------------------------------------------------- module Data.PlanarGraph.AdjRep where -import Data.Aeson-import GHC.Generics (Generic)-import Control.Lens(Bifunctor(..))+import           Control.Lens   (Bifunctor (..))+import           Data.Aeson+import           Data.Bifunctor (second)+import           GHC.Generics   (Generic)  --------------------------------------------------------------------------------  -- | Data type representing the graph in its JSON/Yaml format data Gr v f = Gr { adjacencies :: [v]                  , faces       :: [f]-                 } deriving (Generic)+                 } deriving (Generic, Show, Eq)  instance Bifunctor Gr where   bimap f g (Gr vs fs) = Gr (map f vs) (map g fs)@@ -43,10 +44,10 @@                                         -- vertices. This is not (yet)                                         -- enforced by the data type.                    , vData :: v-                   } deriving (Generic)+                   } deriving (Generic, Show, Eq)  instance Bifunctor Vtx where-  bimap f g (Vtx i as x) = Vtx i (map (\(j,y) -> (j,g y)) as) (f x)+  bimap f g (Vtx i as x) = Vtx i (map (second g) as) (f x)  instance (ToJSON v, ToJSON e)     => ToJSON   (Vtx v e) where   toEncoding = genericToEncoding defaultOptions@@ -58,7 +59,7 @@ data Face f = Face { incidentEdge :: (Int,Int) -- ^ an edge (u,v) s.t. the face                                                -- is right from (u,v)                    , fData        :: f-                   } deriving (Generic,Functor)+                   } deriving (Generic,Functor, Show, Eq)  instance ToJSON f   => ToJSON   (Face f) where   toEncoding = genericToEncoding defaultOptions
src/Data/PlanarGraph/Core.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-} -------------------------------------------------------------------------------- -- |@@ -13,18 +12,19 @@   import           Control.DeepSeq-import           Control.Lens hiding ((.=))+import           Control.Lens               hiding ((.=)) import           Control.Monad.State.Strict import           Data.Aeson-import qualified Data.Foldable as F+import qualified Data.Foldable              as F import           Data.Permutation import           Data.PlanarGraph.Dart-import           Data.Type.Equality (gcastWith, (:~:)(..))-import qualified Data.Vector as V-import qualified Data.Vector.Mutable as MV-import           GHC.Generics (Generic)-import           Unsafe.Coerce (unsafeCoerce)+import           Data.Type.Equality         (gcastWith)+import qualified Data.Vector                as V+import qualified Data.Vector.Mutable        as MV+import           GHC.Generics               (Generic)+import           Unsafe.Coerce              (unsafeCoerce) + --------------------------------------------------------------------------------  --------------------------------------------------------------------------------@@ -32,7 +32,7 @@ -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -49,7 +49,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -90,6 +93,7 @@ -- | Shorthand for vertices in the primal. type VertexId' s = VertexId s Primal +-- | Getter for a VertexId's unique number. unVertexId :: Getter (VertexId s w) Int unVertexId = to _unVertexId @@ -99,7 +103,7 @@ -------------------------------------------------------------------------------- -- * FaceId's --- | The type to reprsent FaceId's+-- | The type to represent FaceId's newtype FaceId s w = FaceId { _unFaceId :: VertexId s (DualOf w) }                    deriving (Eq,Ord,Enum,ToJSON,FromJSON) @@ -145,19 +149,22 @@  -- ** lenses and getters --- | Get the embedding, reprsented as a permutation of the darts, of this+-- | Get the embedding, represented as a permutation of the darts, of this -- graph. embedding :: Getter (PlanarGraph s w v e f) (Permutation (Dart s)) embedding = to _embedding +-- | O\(1\) access, \( O(n) \) update. vertexData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v' e f)                    (V.Vector v) (V.Vector v') vertexData = lens _vertexData (\g vD -> updateData (const vD) id id g) +-- | O\(1\) access, \( O(n) \) update. rawDartData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v e' f)                     (V.Vector e) (V.Vector e') rawDartData = lens _rawDartData (\g dD -> updateData id (const dD) id g) +-- | O\(1\) access, \( O(n) \) update. faceData :: Lens (PlanarGraph s w v e f) (PlanarGraph s w v e f')                  (V.Vector f) (V.Vector f') faceData = lens _faceData (\g fD -> updateData id id (const fD) g)@@ -182,6 +189,9 @@                  (V.Vector (Dart s, e)) (V.Vector (Dart s, e')) edgeData = dartData +++ -- | Helper function to update the data in a planar graph. Takes care to update -- both the data in the original graph as well as in the dual. updateData :: forall s w v e f v' e' f'@@ -222,18 +232,18 @@  -- | Traverse the vertices ----- (^.vertexData) <$> traverseVertices (\i x -> Just (i,x)) myGraph--- Just [(VertexId 0,()),(VertexId 1,()),(VertexId 2,()),(VertexId 3,())]+-- >>> (^.vertexData) <$> traverseVertices (\i x -> Just (i,x)) myGraph+-- Just [(VertexId 0,"u"),(VertexId 1,"v"),(VertexId 2,"w"),(VertexId 3,"x")] -- >>> traverseVertices (\i x -> print (i,x)) myGraph >> pure ()--- (VertexId 0,())--- (VertexId 1,())--- (VertexId 2,())--- (VertexId 3,())+-- (VertexId 0,"u")+-- (VertexId 1,"v")+-- (VertexId 2,"w")+-- (VertexId 3,"x") traverseVertices   :: Applicative m                    => (VertexId s w -> v -> m v')                    -> PlanarGraph s w v e f                    -> m (PlanarGraph s w v' e f)-traverseVertices f = itraverseOf (vertexData.itraversed) (\i -> f (VertexId i))+traverseVertices f = itraverseOf (vertexData.itraversed) (f . VertexId)  -- | Traverses the darts --@@ -254,15 +264,15 @@                 => (Dart s -> e -> m e')                 -> PlanarGraph s w v e f                 -> m (PlanarGraph s w v e' f)-traverseDarts f = itraverseOf (rawDartData.itraversed) (\i -> f (toEnum i))+traverseDarts f = itraverseOf (rawDartData.itraversed) (f . toEnum)  -- | Traverses the faces -- -- >>> traverseFaces (\i x -> print (i,x)) myGraph >> pure ()--- (FaceId 0,())--- (FaceId 1,())--- (FaceId 2,())--- (FaceId 3,())+-- (FaceId 0,"f_3")+-- (FaceId 1,"f_infty")+-- (FaceId 2,"f_1")+-- (FaceId 3,"f_2") traverseFaces   :: Applicative m                 => (FaceId s w -> f -> m f')                 -> PlanarGraph s w v e f@@ -294,7 +304,7 @@ -- -- running time: \(O(n)\). planarGraph    :: [[(Dart s,e)]] -> PlanarGraph s Primal () e ()-planarGraph ds = (planarGraph' perm)&dartData .~ (V.fromList . concat $ ds)+planarGraph ds = planarGraph' perm & dartData .~ (V.fromList . concat $ ds)   where     n     = sum . map length $ ds     perm  = toCycleRep n $ map (map fst) ds@@ -405,75 +415,155 @@  -- | The tail of a dart, i.e. the vertex this dart is leaving from --+-- >>> showWithData myGraph $ tailOf (Dart (Arc 3) Positive) myGraph+-- (VertexId 2,"w")+-- -- running time: \(O(1)\) tailOf     :: Dart s -> PlanarGraph s w v e f -> VertexId s w tailOf d g = VertexId . fst $ lookupIdx (g^.embedding) d  -- | The vertex this dart is heading in to --+-- showWithData myGraph $ headOf (Dart (Arc 3) Positive) myGraph+-- (VertexId 1,"v")+-- -- running time: \(O(1)\) headOf   :: Dart s -> PlanarGraph s w v e f -> VertexId s w headOf d = tailOf (twin d)  -- | endPoints d g = (tailOf d g, headOf d g) --+-- >>> endPoints (Dart (Arc 3) Positive) myGraph+-- (VertexId 2,VertexId 1)+-- -- running time: \(O(1)\) endPoints :: Dart s -> PlanarGraph s w v e f -> (VertexId s w, VertexId s w) endPoints d g = (tailOf d g, headOf d g) - -- | All edges incident to vertex v, in counterclockwise order around v. -----+-- >>> incidentEdges (VertexId 1) myGraph+-- [Dart (Arc 4) -1,Dart (Arc 1) -1,Dart (Arc 3) -1,Dart (Arc 5) +1]+-- >>> mapM_ (print . showWithData myGraph) $ incidentEdges (VertexId 1) myGraph+-- (Dart (Arc 4) -1,"e-")+-- (Dart (Arc 1) -1,"b-")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 5) +1,"g+")+-- >>> mapM_ (print . showWithData myGraph) $ incidentEdges (VertexId 3) myGraph+-- (Dart (Arc 5) -1,"g-") -- -- running time: \(O(k)\), where \(k\) is the output size incidentEdges                :: VertexId s w -> PlanarGraph s w v e f                              -> V.Vector (Dart s) incidentEdges (VertexId v) g = g^?!embedding.orbits.ix v-  -- TODO: The Delaunay triang. stuff seems to produce these in clockwise order instead --- | All incoming edges incident to vertex v, in counterclockwise order around v.+-- | All edges incident to vertex v in incoming direction+-- (i.e. pointing into v) in counterclockwise order around v.+--+-- >>> incomingEdges (VertexId 1) myGraph+-- [Dart (Arc 4) +1,Dart (Arc 1) +1,Dart (Arc 3) +1,Dart (Arc 5) -1]+-- >>> mapM_ (print . showWithData myGraph) $ incomingEdges (VertexId 1) myGraph+-- (Dart (Arc 4) +1,"e+")+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) +1,"d+")+-- (Dart (Arc 5) -1,"g-")+--+-- running time: \(O(k)\), where \(k) is the total number of incident edges of v incomingEdges     :: VertexId s w -> PlanarGraph s w v e f -> V.Vector (Dart s)-incomingEdges v g = V.filter (not . isPositive) $ incidentEdges v g+incomingEdges v g = orient <$> incidentEdges v g+  where+    orient d = if headOf d g == v then d else twin d --- | All outgoing edges incident to vertex v, in counterclockwise order around v.+-- | All edges incident to vertex v in outgoing direction+-- (i.e. pointing away from v) in counterclockwise order around v.+--+-- running time: \(O(k)\), where \(k) is the total number of incident edges of v outgoingEdges     :: VertexId s w -> PlanarGraph s w v e f -> V.Vector (Dart s)-outgoingEdges v g = V.filter isPositive $ incidentEdges v g+outgoingEdges v g = orient <$> incidentEdges v g+  where+    orient d = if tailOf d g == v then d else twin d   -- | Gets the neighbours of a particular vertex, in counterclockwise order -- around the vertex. --+-- >>> mapM_ (print . showWithData myGraph) $ neighboursOf (VertexId 1) myGraph -- around v+-- (VertexId 2,"w")+-- (VertexId 0,"u")+-- (VertexId 2,"w")+-- (VertexId 3,"x")+-- >>> mapM_ (print . showWithData myGraph) $ neighboursOf (VertexId 3) myGraph -- around x+-- (VertexId 1,"v")+-- -- running time: \(O(k)\), where \(k\) is the output size neighboursOf     :: VertexId s w -> PlanarGraph s w v e f -> V.Vector (VertexId s w)-neighboursOf v g = otherVtx <$> incidentEdges v g-  where-    otherVtx d = let u = tailOf d g in if u == v then headOf d g else u+neighboursOf v g = flip tailOf g <$> incomingEdges v g  -- | Given a dart d that points into some vertex v, report the next dart in the--- cyclic order around v.+-- cyclic (counterclockwise) order around v. --+-- >>> nextIncidentEdge (dart 3 "+1") myGraph+-- Dart (Arc 5) +1+-- >>> showWithData myGraph $ nextIncidentEdge (dart 3 "+1") myGraph+-- (Dart (Arc 5) +1,"g+")+-- >>> showWithData myGraph $ nextIncidentEdge (dart 1 "+1") myGraph+-- (Dart (Arc 3) -1,"d-")+-- -- running time: \(O(1)\)-nextIncidentEdge     :: Dart s -> PlanarGraph s w v e f -> Dart s-nextIncidentEdge d g = let perm  = g^.embedding-                           (i,j) = lookupIdx perm d-                       in next (perm^?!orbits.ix i) j+nextIncidentEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+nextIncidentEdge d = nextIncidentEdgeFrom (twin d) +-- | Given a dart d that points into some vertex v, report the previous dart in the+-- cyclic (counterclockwise) order around v.+--+-- >>> prevIncidentEdge (dart 3 "+1") myGraph+-- Dart (Arc 1) -1+-- >>> showWithData myGraph $ prevIncidentEdge (dart 3 "+1") myGraph+-- (Dart (Arc 1) -1,"b-")+--+-- running time: \(O(1)\)+prevIncidentEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+prevIncidentEdge d = prevIncidentEdgeFrom (twin d) --- | Given a dart d that points into some vertex v, report the next dart in the--- cyclic order around v.++-- | Given a dart d that points away from some vertex v, report the+-- next dart in the cyclic (counterclockwise) order around v. --+-- >>> nextIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- Dart (Arc 2) -1+-- >>> showWithData myGraph $ nextIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- (Dart (Arc 2) -1,"c-")+-- >>> showWithData myGraph $ nextIncidentEdgeFrom (dart 1 "+1") myGraph+-- (Dart (Arc 0) +1,"a+")+-- -- running time: \(O(1)\)-prevIncidentEdge     :: Dart s -> PlanarGraph s w v e f -> Dart s-prevIncidentEdge d g = let perm  = g^.embedding-                           (i,j) = lookupIdx perm d-                       in previous (perm^?!orbits.ix i) j+nextIncidentEdgeFrom     :: Dart s -> PlanarGraph s w v e f -> Dart s+nextIncidentEdgeFrom d g = let perm  = g^.embedding+                               (i,j) = lookupIdx perm d+                           in next (perm^?!orbits.ix i) j  +-- | Given a dart d that points into away from vertex v, report the previous dart in the+-- cyclic (counterclockwise) order around v.+--+-- >>> prevIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- Dart (Arc 4) +1+-- >>> showWithData myGraph $ prevIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- (Dart (Arc 4) +1,"e+")+-- >>> showWithData myGraph $ prevIncidentEdgeFrom (Dart (Arc 1) Positive) myGraph+-- (Dart (Arc 2) +1,"c+")+--+-- running time: \(O(1)\)+prevIncidentEdgeFrom     :: Dart s -> PlanarGraph s w v e f -> Dart s+prevIncidentEdgeFrom d g = let perm  = g^.embedding+                               (i,j) = lookupIdx perm d+                           in previous (perm^?!orbits.ix i) j++ -------------------------------------------------------------------------------- -- * Access data -+-- | General interface to accessing vertex data, dart data, and face data. class HasDataOf g i where   type DataOf g i   -- | get the data associated with the value i.@@ -495,6 +585,9 @@   -- | Data corresponding to the endpoints of the dart+--+-- >>> myGraph^.endPointDataOf (Dart (Arc 3) Positive)+-- ("w","v") endPointDataOf   :: Dart s -> Getter (PlanarGraph s w v e f) (v,v) endPointDataOf d = to $ endPointData d @@ -540,3 +633,35 @@                         (g^.rawDartData)                         (g^.vertexData)                         g++++--------------------------------------------------------------------------------++-- myGraph :: PlanarGraph () Primal String String String+-- myGraph = planarGraph [ [ (Dart aA Negative, "a-")+--                             , (Dart aC Positive, "c+")+--                             , (Dart aB Positive, "b+")+--                             , (Dart aA Positive, "a+")+--                             ]+--                           , [ (Dart aE Negative, "e-")+--                             , (Dart aB Negative, "b-")+--                             , (Dart aD Negative, "d-")+--                             , (Dart aG Positive, "g+")+--                             ]+--                           , [ (Dart aE Positive, "e+")+--                             , (Dart aD Positive, "d+")+--                             , (Dart aC Negative, "c-")+--                             ]+--                           , [ (Dart aG Negative, "g-")+--                             ]+--                           ]+--           & vertexData .~ V.fromList ["u","v","w","x"]+--           & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--   where+--     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]++-- dart i s = Dart (Arc i) (read s)++-- showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+-- showWithData g i = (i, g^.dataOf i)
src/Data/PlanarGraph/Dart.hs view
@@ -62,7 +62,16 @@ data Dart s = Dart { _arc       :: !(Arc s)                    , _direction :: !Direction                    } deriving (Eq,Ord,Generic)-makeLenses ''Dart++-- | Arc lens.+arc :: Lens' (Dart s) (Arc s)+arc = lens _arc (\d a -> d{_arc = a})++-- | Direction lens.+direction :: Lens' (Dart s) Direction+direction = lens _direction (\d dir -> d{_direction = dir})++-- makeLenses ''Dart  instance NFData (Dart s) 
src/Data/PlanarGraph/Dual.hs view
@@ -24,7 +24,7 @@ -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -41,7 +41,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -61,14 +64,17 @@  -- | The face to the left of the dart --+-- -- >>> leftFace (dart 1 "+1") myGraph -- FaceId 1+-- >>> showWithData myGraph $ leftFace (dart 1 "+1") myGraph+-- (FaceId 1,"f_infty") -- >>> leftFace (dart 1 "-1") myGraph -- FaceId 2--- >>> leftFace (dart 2 "+1") myGraph--- FaceId 2--- >>> leftFace (dart 0 "+1") myGraph--- FaceId 0+-- >>> showWithData myGraph $ leftFace (dart 1 "-1") myGraph+-- (FaceId 2,"f_1")+-- >>> showWithData myGraph $ leftFace (dart 0 "+1") myGraph+-- (FaceId 0,"f_3") -- -- running time: \(O(1)\). leftFace     :: Dart s -> PlanarGraph s w v e f -> FaceId s w@@ -77,50 +83,95 @@  -- | The face to the right of the dart --+-- -- >>> rightFace (dart 1 "+1") myGraph -- FaceId 2+-- >>> showWithData myGraph $ rightFace (dart 1 "+1") myGraph+-- (FaceId 2,"f_1") -- >>> rightFace (dart 1 "-1") myGraph -- FaceId 1--- >>> rightFace (dart 2 "+1") myGraph--- FaceId 1--- >>> rightFace (dart 0 "+1") myGraph--- FaceId 1+-- >>> showWithData myGraph $ rightFace (dart 1 "-1") myGraph+-- (FaceId 1,"f_infty")+-- >>> showWithData myGraph $ rightFace (dart 0 "+1") myGraph+-- (FaceId 1,"f_infty") -- -- running time: \(O(1)\). rightFace     :: Dart s -> PlanarGraph s w v e f -> FaceId s w rightFace d g = FaceId . tailOf d $ _dual g  --- | Get the next edge along the face+-- | Get the next edge (in clockwise order) along the face that is to+-- the right of this dart. --+-- >> showWithData myGraph $ nextEdge (dart 1 "+1") myGraph+-- (Dart (Arc 3) -1,"d-")+-- >> showWithData myGraph $ nextEdge (dart 2 "+1") myGraph+-- (Dart (Arc 4) +1,"e+")+-- -- running time: \(O(1)\). nextEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s-nextEdge d = nextIncidentEdge d . _dual+nextEdge d = nextIncidentEdgeFrom d . _dual+  -- prevIncidentEdge (twin d) (_dual g)+  -- where+  --   f = rightFace d g --- | Get the previous edge along the face+-- | Get the previous edge (in clockwise order) along the face that is+-- to the right of this dart. --+-- >>> showWithData myGraph $ prevEdge (dart 1 "+1") myGraph+-- (Dart (Arc 2) -1,"c-")+-- >>> showWithData myGraph $ prevEdge (dart 3 "-1") myGraph+-- (Dart (Arc 1) +1,"b+")+-- -- running time: \(O(1)\).-prevEdge :: Dart s -> PlanarGraph s w v e f -> Dart s-prevEdge d = prevIncidentEdge d . _dual-+prevEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+prevEdge d = prevIncidentEdgeFrom d . _dual  -- | Gets a dart bounding this face. I.e. a dart d such that the face lies to -- the right of the dart.+--+-- >>> boundaryDart (FaceId $ VertexId 2) myGraph+-- Dart (Arc 1) +1+-- >>> showWithData myGraph $ boundaryDart (FaceId $ VertexId 2) myGraph+-- (Dart (Arc 1) +1,"b+")+-- >>> showWithData myGraph $ boundaryDart (FaceId $ VertexId 1) myGraph+-- (Dart (Arc 2) +1,"c+") boundaryDart   :: FaceId s w -> PlanarGraph s w v e f -> Dart s boundaryDart f = V.head . boundary f--- TODO: make sure that this is indeed to the right. --- | The darts bounding this face, for internal faces in clockwise order, for--- the outer face in counter clockwise order.+-- | The darts bounding this face. The darts are reported in order+-- along the face. This means that for internal faces the darts are+-- reported in *clockwise* order along the boundary, whereas for the+-- outer face the darts are reported in counter clockwise order. --+-- >>> boundary (FaceId $ VertexId 2) myGraph+-- [Dart (Arc 1) +1,Dart (Arc 3) -1,Dart (Arc 2) -1]+-- >>> mapM_ (print . showWithData myGraph) $ boundary (FaceId $ VertexId 2) myGraph+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 2) -1,"c-")+-- >>> boundary (FaceId $ VertexId 1) myGraph+-- [Dart (Arc 2) +1,Dart (Arc 4) +1,Dart (Arc 1) -1,Dart (Arc 0) +1]+-- >>> mapM_ (print . showWithData myGraph) $ boundary (FaceId $ VertexId 1) myGraph+-- (Dart (Arc 2) +1,"c+")+-- (Dart (Arc 4) +1,"e+")+-- (Dart (Arc 1) -1,"b-")+-- (Dart (Arc 0) +1,"a+") -- -- running time: \(O(k)\), where \(k\) is the output size. boundary              :: FaceId s w -> PlanarGraph s w v e f -> V.Vector (Dart s) boundary (FaceId v) g = incidentEdges v $ _dual g ---- | Generates the darts incident to a face, starting with the given dart.+-- | Given a dart d, generates the darts bounding the face that is to+-- the right of the given dart. The darts are reported in order along+-- the face. This means that for internal faces the darts are reported+-- in *clockwise* order along the boundary, whereas for the outer face+-- the darts are reported in counter clockwise order. --+-- >>> mapM_ (print . showWithData myGraph) $ boundary' (dart 1 "+1") myGraph+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 2) -1,"c-") -- -- \(O(k)\), where \(k\) is the number of darts reported boundary'     :: Dart s -> PlanarGraph s w v e f -> V.Vector (Dart s)@@ -132,13 +183,22 @@         f i = let (a,b) = V.splitAt i v  in b <> a  --- | The vertices bounding this face, for internal faces in clockwise order, for--- the outer face in counter clockwise order.+-- | The vertices bounding this face, for internal faces in clockwise+-- order, for the outer face in counter clockwise order. --+-- >>> mapM_ (print . showWithData myGraph) $ boundaryVertices (FaceId $ VertexId 2) myGraph+-- (VertexId 0,"u")+-- (VertexId 1,"v")+-- (VertexId 2,"w")+-- >>> mapM_ (print . showWithData myGraph) $ boundaryVertices (FaceId $ VertexId 1) myGraph+-- (VertexId 0,"u")+-- (VertexId 2,"w")+-- (VertexId 1,"v")+-- (VertexId 0,"u") -- -- running time: \(O(k)\), where \(k\) is the output size. boundaryVertices     :: FaceId s w -> PlanarGraph s w v e f -> V.Vector (VertexId s w)-boundaryVertices f g = fmap (flip tailOf g) $ boundary f g+boundaryVertices f g = flip tailOf g <$> boundary f g  -- -- | Gets the next dart along the face -- nextDart     :: Dart s -> PlanarGraph s w v e f -> Dart s
src/Data/PlanarGraph/IO.hs view
@@ -13,22 +13,20 @@ module Data.PlanarGraph.IO where  import           Control.Lens-import           Control.Monad (forM_) import           Control.Monad.State.Strict import           Data.Aeson import           Data.Bifunctor import           Data.Ext-import qualified Data.Foldable as F-import           Data.Maybe (fromJust)+import qualified Data.Foldable               as F+import           Data.Maybe                  (fromJust) import           Data.Permutation-import           Data.PlanarGraph.AdjRep (Face(Face), Vtx(Vtx),Gr(Gr))+import           Data.PlanarGraph.AdjRep     (Face (Face), Gr (Gr), Vtx (Vtx)) import           Data.PlanarGraph.Core import           Data.PlanarGraph.Dart import           Data.PlanarGraph.Dual import           Data.PlanarGraph.EdgeOracle-import           Data.Proxy-import qualified Data.Vector as V-import qualified Data.Vector.Mutable as MV+import qualified Data.Vector                 as V+import qualified Data.Vector.Mutable         as MV  -------------------------------------------------------------------------------- @@ -37,7 +35,7 @@   toJSON     = toJSON     . toAdjRep  instance (FromJSON v, FromJSON e, FromJSON f) => FromJSON (PlanarGraph s Primal v e f) where-  parseJSON v = fromAdjRep (Proxy :: Proxy s) <$> parseJSON v+  parseJSON v = fromAdjRep @s <$> parseJSON v  -------------------------------------------------------------------------------- @@ -72,13 +70,13 @@ -- should be in counter clockwise order. -- -- running time: \(O(n)\)-fromAdjRep                  :: proxy s -> Gr (Vtx v e) (Face f) -> PlanarGraph s Primal v e f-fromAdjRep px gr@(Gr as fs) = g&vertexData .~ reorder vs' _unVertexId-                               &dartData   .~ ds-                               &faceData   .~ reorder fs' (_unVertexId._unFaceId)+fromAdjRep            :: forall s v e f. Gr (Vtx v e) (Face f) -> PlanarGraph s Primal v e f+fromAdjRep (Gr as fs) = g&vertexData .~ reorder vs' _unVertexId+                         &dartData   .~ ds+                         &faceData   .~ reorder fs' (_unVertexId._unFaceId)   where     -- build the actual graph using the adjacencies-    g = buildGraph px gr+    g = buildGraph as     -- build an edge oracle so that we can quickly lookup the dart corresponding to a     -- pair of vertices.     oracle = edgeOracle g@@ -96,14 +94,40 @@    -- TODO: Properly handle graphs with self-loops +-- | Read a planar graph, given by its adjacencylists in counter clockwise order.+--+-- pre: no self-loops and no multiedges+--+-- running time: \(O(n)\)+fromAdjRep'    :: forall s v e. [Vtx v e] -> PlanarGraph s Primal v e ()+fromAdjRep' as = g&vertexData .~ reorder vs' _unVertexId+                  &dartData   .~ ds+  where+    -- build the actual graph using the adjacencies+    g = buildGraph as+    -- build an edge oracle so that we can quickly lookup the dart corresponding to a+    -- pair of vertices.+    oracle = edgeOracle g+    -- function to lookup a given dart+    findEdge' u v = fromJust $ findDart u v oracle++    vs' = V.fromList [ VertexId vi :+ v     | Vtx vi _ v <- as ]+    ds = V.fromList $ concatMap (\(Vtx vi us _) ->+                                   [(findEdge' (VertexId vi) (VertexId ui), x) | (ui,x) <- us]+                                ) as++  -- TODO: Properly handle graphs with self-loops++ -- | Builds the graph from the adjacency lists (but ignores all associated data)-buildGraph              :: proxy s -> Gr (Vtx v e) (Face f) -> PlanarGraph s Primal () () ()-buildGraph _ (Gr as' _) = fromAdjacencyLists as+buildGraph     :: forall s v e. [Vtx v e] -> PlanarGraph s Primal () () ()+buildGraph as' = fromAdjacencyLists as   where     as = [ (VertexId vi, V.fromList [VertexId ui | (ui,_) <- us])          | Vtx vi us _ <- as'          ] + -- make sure we order the data values appropriately reorder     :: V.Vector (i :+ a) -> (i -> Int) -> V.Vector a reorder v f = V.create $ do@@ -126,7 +150,7 @@ fromAdjacencyLists adjM = planarGraph' . toCycleRep n $ perm   where     n    = sum . fmap length $ perm-    perm = map toOrbit  $ adjM'+    perm = map toOrbit adjM'      adjM' = fmap (second F.toList) adjM @@ -142,7 +166,9 @@     toOrbit (u,adjU) = concatMap (toDart u) adjU      -- if u = v we have a self-loop, so we add both a positive and a negative dart-    toDart u v = let Just a = findEdge u v oracle+    toDart u v = let a = case findEdge u v oracle of+                           Nothing -> error $ "edge not found? " <> show (u,v)+                           Just a' -> a'                  in case u `compare` v of                       LT -> [Dart (Arc a) Positive]                       EQ -> [Dart (Arc a) Positive, Dart (Arc a) Negative]
+ src/Data/PlanarGraph/Immutable.hs view
@@ -0,0 +1,1404 @@+{-# LANGUAGE RecordWildCards #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.PlanarGraph.Immutable+-- Copyright   :  (C) David Himmelstrup+-- License     :  see the LICENSE file+-- Maintainer  :  David Himmelstrup+--+-- A graph is planar if it can be drawn on a flat piece of+-- paper without any crossing edges. More theory is explained on wikipedia:+-- <https://en.wikipedia.org/wiki/Planar_graph>+--+-- This module describes the connectivity of planar graphs without knowing+-- the 2D coordinates of each vertex. Algorithms that require the vertex+-- positions (such as planar point locators or mesh smoothers) have to store+-- that information somewhere else. Vertices are identified by dense, consecutive+-- integers and can be efficiently used with arrays or finite maps.+-- +-- A planar graph consists of directed edges (also called half-edges or darts),+-- vertices, and faces. If a face lies on the outside of a set of vertices, this+-- face is called a boundary.+--+-- The simplest planar graph has just three vertices and three edges:+--+-- @'pgFromFaces' [[0,1,2]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- The above pictures shows three vertices (named @'0'@, @'1'@, and @'2'@), a single face+-- (named @'0'@ with an underscore), and 6 half-edges (named @'0'@ through @'5'@).+-- Vertices, faces, and half-edges can be efficiently queried and traversed.+--+-- >>> let pg = pgFromFaces [[0,1,2]]+-- >>> pgFaces pg+-- [Face 0]+-- >>> faceBoundary (Face 0) pg+-- [Vertex 1,Vertex 2,Vertex 0]+--+--+-- == Planar graph examples:+--+-- Faces in planar graphs do not have to be triangular:+--+-- @'pgFromFaces' [[0,1,2,3]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- Vertices may be interior or lie on a boundary:+--+-- @'pgFromFaces' [[0,1,2,3],[4,3,2,1]]@+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- >>> pgFaces pg+-- [Face 0,Face 1]+-- >>> vertexIsBoundary (Vertex 0) pg+-- True+-- >>> vertexIsBoundary (Vertex 2) pg+-- False+--+-- Planar graphs may have multiple boundaries. Notice how the area between vertices+-- @'1'@, @'2'@ and @'3'@ does not have a face ID:+--+-- @'pgFromFaces' [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]@+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+-- >>> pgFaces pg+-- [Face 0,Face 1,Face 2,Face 3,Face 4,Face 5]+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+-- >>> faceBoundary (Boundary 0) pg {- Outer boundary -}+-- [Vertex 0,Vertex 4,Vertex 5]+-- >>> faceBoundary (Boundary 1) pg {- Inner boundary -}+-- [Vertex 1,Vertex 2,Vertex 3]+--+-- Planar graphs may also have multiple unconnected components but they cannot be+-- automatically rendered:+--+-- >>> let pg = pgFromFaces [[0,1,2], [3,4,5]]+-- >>> pgFaces pg+-- [Face 0,Face 1]+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 1,Vertex 2]+-- >>> faceBoundary (Boundary 1) pg+-- [Vertex 3,Vertex 4,Vertex 5]+--+-- == Big-O Notation+--+-- When describing runtime complexity, @n@ refers to the size of the graph+-- (vertices, half-edges, faces, etcs). Some functions are output-sensitive+-- and use @k@ to indicate the amount of data consumed. For example,+-- 'vertexNeighbours' runs in \( O(k) \) and taking the first neighbour is therefore+-- an \( O(1) \) operation (because k=1).+--------------------------------------------------------------------------------+module Data.PlanarGraph.Immutable+  ( -- * Planar graphs+    PlanarGraph+  , pgFromFaces   -- :: [[VertexId]] -> PlanarGraph+  , pgFromFacesCV -- :: [CircularVector VertexId] -> PlanarGraph+  , pgVertices    -- :: PlanarGraph -> [Vertex]+  , pgEdges       -- :: PlanarGraph -> [Edge]+  , pgHalfEdges   -- :: PlanarGraph -> [HalfEdge]+  , pgFaces       -- :: PlanarGraph -> [Face]+  , pgBoundaries  -- :: PlanarGraph -> [Face]++    -- * Elements+    -- ** Vertices+  , Vertex(..)+  , vertexHalfEdge              -- :: Vertex -> PlanarGraph -> HalfEdge+  , vertexIsInterior            -- :: Vertex -> PlanarGraph -> Bool+  , vertexIsBoundary            -- :: Vertex -> PlanarGraph -> Bool+  , vertexOutgoingHalfEdges     -- :: Vertex -> PlanarGraph -> [HalfEdge]+  , vertexIncomingHalfEdges     -- :: Vertex -> PlanarGraph -> [HalfEdge]+  , vertexNeighbours            -- :: Vertex -> PlanarGraph -> [Vertex]++    -- ** Edges+  , Edge(..)+  , edgeHalfEdges        -- :: Edge -> (HalfEdge, HalfEdge)++    -- ** Half-edges+  , HalfEdge(..)+  , halfEdgeNext         -- :: HalfEdge -> PlanarGraph -> HalfEdge+  , halfEdgePrev         -- :: HalfEdge -> PlanarGraph -> HalfEdge+  , halfEdgeTwin         -- :: HalfEdge -> HalfEdge+  , halfEdgeNextOutgoing -- :: HalfEdge -> PlanarGraph -> HalfEdge+  , halfEdgeNextIncoming -- :: HalfEdge -> PlanarGraph -> HalfEdge+  , halfEdgeVertex       -- :: HalfEdge -> PlanarGraph -> Vertex+  , halfEdgeTailVertex   -- :: HalfEdge -> PlanarGraph -> Vertex+  , halfEdgeTipVertex    -- :: HalfEdge -> PlanarGraph -> Vertex+  , halfEdgeFace         -- :: HalfEdge -> PlanarGraph -> Face+  , halfEdgeIsInterior   -- :: HalfEdge -> PlanarGraph -> Bool+  , halfEdgeIsBoundary   -- :: HalfEdge -> PlanarGraph -> Bool++    -- ** Faces+  , Face(..), FaceId+  , faceMember     -- :: Face -> PlanarGraph -> Bool+  , faceId         -- :: Face -> FaceId+  , faceHalfEdge   -- :: Face -> PlanarGraph -> HalfEdge+  , faceIsInterior -- :: Face -> Bool+  , faceIsBoundary -- :: Face -> Bool+  , faceHalfEdges  -- :: Face -> PlanarGraph -> CircularVector HalfEdge+  , faceBoundary   -- :: Face -> PlanarGraph -> CircularVector Vertex++    -- * Mutation+  , pgMutate       -- :: PlanarGraph -> (forall s. Mut.PlanarGraph s -> ST s ()) -> PlanarGraph+  , pgCreate       -- :: (forall s. ST s (Mut.PlanarGraph s)) -> PlanarGraph+  , pgThaw         -- :: PlanarGraph -> ST s (Mut.PlanarGraph s)+  , pgFreeze       -- :: Mut.PlanarGraph s -> ST s PlanarGraph+  , pgUnsafeThaw   -- :: PlanarGraph -> ST s (Mut.PlanarGraph s)+  , pgUnsafeFreeze -- :: Mut.PlanarGraph s -> ST s PlanarGraph++    -- * Misc+  , tutteEmbedding -- :: PlanarGraph -> Vector.Vector (V2 Double)+  )+  where++import           Control.Monad+import           Control.Monad.ST+import           Data.Bits+import           Data.Coerce+import           Data.Hashable+import           Data.PlanarGraph.Internal (FaceId, HalfEdgeId, VertexId)+import qualified Data.PlanarGraph.Internal as Mut+import qualified Data.PlanarGraph.Mutable  as Mut+import           Data.Proxy+import           Data.STRef+import           Data.Vector               (Vector)+import qualified Data.Vector               as Vector+import           Data.Vector.Circular      (CircularVector)+import qualified Data.Vector.Circular      as CV+import qualified Data.Vector.Mutable       as V+import           GHC.Exts+import           Linear.Matrix             (luSolve)+import           Linear.V+import           Linear.V2++-- import Debug.Trace++-------------------------------------------------------------------------------+-- Elements: Half-edges, vertices, faces.+++-- | Half-edges are directed edges between vertices. All Half-edge have a twin+--   in the opposite direction. Half-edges have individual identity but are always+--   created in pairs.+newtype HalfEdge = HalfEdge {halfEdgeId :: Int}+  deriving (Eq, Hashable)++instance Show HalfEdge where+  showsPrec d (HalfEdge v) = showParen (d > 10) $+    showString "HalfEdge " . shows v++instance Read HalfEdge where+  readsPrec d = readParen (d > app_prec) $ \r ->+      [ (HalfEdge v, t)+      | ("HalfEdge", s) <- lex r, (v, t) <- reads s ]+    where app_prec = 10++-- | Edges are bidirectional and connect two vertices. No two edges are allowed+-- to cross.+newtype Edge = Edge {edgeId :: Int}+  deriving (Eq, Hashable)++instance Show Edge where+  showsPrec d (Edge v) = showParen (d > 10) $+    showString "Edge " . shows v++instance Read Edge where+  readsPrec d = readParen (d > app_prec) $ \r ->+      [ (Edge v, t)+      | ("Edge", s) <- lex r, (v, t) <- reads s ]+    where app_prec = 10++-- | Graph vertices. For best performance, make sure to use consecutive numbers.+newtype Vertex = Vertex {vertexId :: Int}+  deriving (Eq, Hashable)++instance Show Vertex where+  showsPrec d (Vertex v) = showParen (d > 10) $+    showString "Vertex " . shows v++instance Read Vertex where+  readsPrec d = readParen (d > app_prec) $ \r ->+      [ (Vertex v, t)+      | ("Vertex", s) <- lex r, (v, t) <- reads s ]+    where app_prec = 10++-- | Faces are the areas divided by edges. If a face is not surrounded by a set of vertices,+--   it is called a boundary.+data Face = Face FaceId | Boundary FaceId+  deriving (Eq, Read, Show)++-------------------------------------------------------------------------------+-- Planar graph++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.++-- FIXME: Use STRefU ?+-- PlanarGraph with 0 vertices: No edges, no vertices, no faces.+-- PlanarGraph with 1 vertex: No edges, no interior faces.+-- PlanarGraph with 2 vertices: One edge, no interior faces.+-- PlanarGraph with 3+ vertices: Usual properties hold.+-- | Immutable planar graph.+data PlanarGraph = PlanarGraph+  { pgHalfEdgeNext   :: !(Vector HalfEdgeId) -- HalfEdge indexed+  , pgHalfEdgePrev   :: !(Vector HalfEdgeId) -- HalfEdge indexed+  , pgHalfEdgeVertex :: !(Vector VertexId)   -- HalfEdge indexed+  , pgHalfEdgeFace   :: !(Vector FaceId)     -- HalfEdge indexed+  , pgVertexEdges    :: !(Vector HalfEdgeId) -- Vertex indexed+  , pgFaceEdges      :: !(Vector HalfEdgeId) -- Face indexed+  , pgBoundaryEdges  :: !(Vector HalfEdgeId) -- Boundary faces+  } deriving Eq++panic :: String -> String -> a+panic tag msg = error $ "Data.PlanarGraph.Immutable." ++ tag ++ ": " ++ msg+++-- Disabled since hashes are not stable across different versions of hashable.+-- // $setup+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618+-- >>> hash $ pgFromFaces [[1,2,3]]+-- 2486673127436488352+-- >>> hash $ pgFromFaces [[0,1,2,3]]+-- 2506803680640023584+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232+--++-- | \( O(n \log n) \)+--+--   Construct a planar graph from a list of faces. Vertices are assumed to be dense+--   (ie without gaps) but this only affects performance, not correctness. Memory+--   usage is defined by the largest vertex ID. That means @'pgFromFaces' [[0,1,2]]@+--   has the same connectivity as @'pgFromFaces' [[7,8,9]]@ but uses three times less+--   memory.+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- @+-- 'pgFromFaces' [[1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2486673127436488352.svg>>+--+-- @since 0.12.0.0+pgFromFaces :: [[VertexId]] -> PlanarGraph+pgFromFaces = pgFromFacesCV . map CV.unsafeFromList++-- | \( O(n \log n) \)+--+--   Construct a planar graph from a list of faces. This is a slightly more+--   efficient version of 'pgFromFacesCV'.+-- +-- @since 0.12.0.0+pgFromFacesCV :: [CircularVector VertexId] -> PlanarGraph+pgFromFacesCV faces = pgCreate $ Mut.pgFromFacesCV faces++-- fromFaces' :: Int -> Int -> Int -> [CircularVector VertexId] -> ST s (PlanarGraph)+-- fromFaces' nFaces nHalfEdges maxVertexId faces = do+--   undefined++-- dualTree :: Face -> ST s (Tree Face)+-- dualTree = undefined++instance Hashable PlanarGraph where+  hashWithSalt salt = hashWithSalt salt . pgHash+  hash = pgHash++-- | O(n)+-- +-- @since 0.12.0.0+pgHash :: PlanarGraph -> Int+pgHash pg =+  let loop [] salt = salt+      loop (edgeId:rest) salt =+        let he = HalfEdge (edgeId*2)+            vTail = halfEdgeTailVertex he pg+            vTip = halfEdgeTipVertex he pg+        in loop rest (hashWithSalt salt (vTail, vTip))+  in abs $ loop [0..Vector.length (pgHalfEdgeNext pg)`div`2-1] 0++-------------------------------------------------------------------------------+-- Vertices++-- | O(1)+vertexCheck :: String -> Vertex -> PlanarGraph -> a -> a+vertexCheck tag (Vertex vId) pg _val+  | vId >= Vector.length (pgVertexEdges pg) || vId < 0 =+    panic tag ("Out-of-bounds vertex access: " ++ show vId)+  | not (halfEdgeIsValid (HalfEdge (pgVertexEdges pg Vector.! vId))) =+    panic tag ("Tried to access deleted vertex: " ++ show vId)+vertexCheck _tag _face _pg val = val++-- | \( O(k) \)+--   +--   List all vertices in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgVertices pg+-- [Vertex 0,Vertex 1,Vertex 2]+--+-- @since 0.12.0.0+pgVertices :: PlanarGraph -> [Vertex]+pgVertices pg =+  [ Vertex v+  | v <- [0 .. Vector.length (pgVertexEdges pg)-1 ]+  , halfEdgeIsValid (HalfEdge $ pgVertexEdges pg Vector.! v)+  ]++-- -- | \( O(1) \)+-- vertexFromId :: VertexId -> Vertex+-- vertexFromId vId = Vertex vId++-- -- | \( O(1) \)+-- vertexId :: Vertex -> VertexId+-- vertexId (Vertex vId) = vId++-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618++-- | \( O(1) \)+--+--   Each vertex has an assigned half-edge with the following properties:+--+--   @'halfEdgeVertex' ('vertexHalfEdge' vertex pg) pg = vertex@+--+--   @'faceIsInterior' ('halfEdgeFace' ('vertexHalfEdge' vertex pg) pg) = True@+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> vertexHalfEdge (Vertex 0) pg+-- HalfEdge 4+--+-- >>> vertexHalfEdge (Vertex 1) pg+-- HalfEdge 0+--+-- >>> vertexHalfEdge (Vertex 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexHalfEdge: Out-of-bounds vertex access: 6+-- ...+--+-- >>> vertexHalfEdge (Vertex (-10)) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexHalfEdge: Out-of-bounds vertex access: -10+-- ...+--+-- >>> halfEdgeVertex (vertexHalfEdge (Vertex 2) pg) pg+-- Vertex 2+--+-- >>> halfEdgeFace (vertexHalfEdge (Vertex 0) pg) pg+-- Face 0+--+-- @since 0.12.0.0+vertexHalfEdge :: Vertex -> PlanarGraph -> HalfEdge+vertexHalfEdge vertex pg | vertexCheck "vertexHalfEdge" vertex pg False = undefined+vertexHalfEdge (Vertex vId) pg = HalfEdge $ pgVertexEdges pg Vector.! vId+++-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(1) \)+--+--   Returns @True@ iff the vertex lies on a boundary.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIsBoundary (Vertex 0) pg+-- True+--+-- >>> vertexIsBoundary (Vertex 2) pg+-- False+--+-- >>> vertexIsBoundary (Vertex 4) pg+-- True+--+-- >>> vertexIsBoundary (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIsBoundary: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIsBoundary :: Vertex -> PlanarGraph -> Bool+vertexIsBoundary vertex pg | vertexCheck "vertexIsBoundary" vertex pg False = undefined+vertexIsBoundary vertex pg =+    faceIsBoundary $ halfEdgeFace (halfEdgeTwin $ vertexHalfEdge vertex pg) pg++-- | \( O(1) \)+--+--   Returns @True@ iff the vertex is interior, ie. does not lie on a boundary.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIsInterior (Vertex 0) pg+-- False+--+-- >>> vertexIsInterior (Vertex 2) pg+-- True+--+-- >>> vertexIsInterior (Vertex 4) pg+-- False+--+-- >>> vertexIsInterior (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIsInterior: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIsInterior :: Vertex -> PlanarGraph -> Bool+vertexIsInterior vertex pg | vertexCheck "vertexIsInterior" vertex pg False = undefined+vertexIsInterior vertex pg = not $ vertexIsBoundary vertex pg++-- | \( O(k) \)+--+--   Query outgoing half-edges from a given vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexOutgoingHalfEdges (Vertex 1) pg+-- [HalfEdge 0,HalfEdge 11,HalfEdge 3]+--+-- Each half-edge will point out from the origin vertex:+--+-- >>> map (`halfEdgeVertex` pg) $ vertexOutgoingHalfEdges (Vertex 1) pg+-- [Vertex 1,Vertex 1,Vertex 1]+--+-- >>> map (`halfEdgeTipVertex` pg) $ vertexOutgoingHalfEdges (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> vertexOutgoingHalfEdges (Vertex 2) pg+-- [HalfEdge 2,HalfEdge 5]+--+-- >>> vertexOutgoingHalfEdges (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexOutgoingHalfEdges: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexOutgoingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+vertexOutgoingHalfEdges vertex pg | vertexCheck "vertexOutgoingHalfEdges" vertex pg False = undefined+vertexOutgoingHalfEdges vertex pg = first : build (g (advance first))+  where+    advance he = halfEdgeNext (halfEdgeTwin he) pg+    first = vertexHalfEdge vertex pg+    g :: HalfEdge -> (HalfEdge -> b -> b) -> b -> b+    g he cons nil+      | he == first = nil+      | otherwise   = cons he (g (advance he) cons nil)++-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(k) \)+--+--   Query incoming half-edges from a given vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexIncomingHalfEdges (Vertex 1) pg+-- [HalfEdge 1,HalfEdge 10,HalfEdge 2]+--+-- >>> map (`halfEdgeVertex` pg) $ vertexIncomingHalfEdges (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> map (`halfEdgeTipVertex` pg) $ vertexIncomingHalfEdges (Vertex 1) pg+-- [Vertex 1,Vertex 1,Vertex 1]+--+-- >>> vertexIncomingHalfEdges (Vertex 2) pg+-- [HalfEdge 3,HalfEdge 4]+--+-- >>> vertexIncomingHalfEdges (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexIncomingHalfEdges: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexIncomingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+vertexIncomingHalfEdges vertex pg | vertexCheck "vertexIncomingHalfEdges" vertex pg False = undefined+vertexIncomingHalfEdges vertex pg = map halfEdgeTwin $ vertexOutgoingHalfEdges vertex pg++-- | \( O(k) \)+--+--   Query vertex neighbours in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> vertexNeighbours (Vertex 0) pg+-- [Vertex 3,Vertex 1]+--+-- >>> vertexNeighbours (Vertex 1) pg+-- [Vertex 0,Vertex 4,Vertex 2]+--+-- >>> vertexNeighbours (Vertex 2) pg+-- [Vertex 1,Vertex 3]+--+-- >>> vertexNeighbours (Vertex 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.vertexNeighbours: Out-of-bounds vertex access: 12+-- ...+--+-- @since 0.12.0.0+vertexNeighbours :: Vertex -> PlanarGraph -> [Vertex]+vertexNeighbours vertex pg | vertexCheck "vertexNeighbours" vertex pg False = undefined+vertexNeighbours vertex pg = map (`halfEdgeVertex` pg) $ vertexIncomingHalfEdges vertex pg++-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++-------------------------------------------------------------------------------+-- Edges++-- | \( O(k) \)+--   +--   List all edges in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgEdges pg+-- [Edge 0,Edge 1,Edge 2]+--+-- >>> map edgeHalfEdges $ pgEdges pg+-- [(HalfEdge 0,HalfEdge 1),(HalfEdge 2,HalfEdge 3),(HalfEdge 4,HalfEdge 5)]+--+-- @since 0.12.0.0+pgEdges :: PlanarGraph -> [Edge]+pgEdges pg =+  [ Edge e+  | e <- [0 .. Vector.length (pgHalfEdgeNext pg) `div` 2 -1]+  , let he = e*2+  , halfEdgeIsValid (HalfEdge he)+  ]++-- | \( O(1) \)+--+--   Split a bidirectional edge into directed half-edges.+--+-- @since 0.12.0.0+edgeHalfEdges :: Edge -> (HalfEdge, HalfEdge)+edgeHalfEdges (Edge e) = (HalfEdge $ e*2, HalfEdge $ e*2+1)++-------------------------------------------------------------------------------+-- Half-edges++-- | O(1)+halfEdgeCheck :: String -> HalfEdgeId -> PlanarGraph -> a -> a+halfEdgeCheck tag eId pg _val+  | eId >= Vector.length (pgHalfEdgeVertex pg) || eId < 0 =+    panic tag ("Out-of-bounds half-edge access: " ++ show eId)+  | pgHalfEdgeVertex pg Vector.! eId < 0 =+    panic tag ("Tried to access deleted half-edge: " ++ show eId)+halfEdgeCheck _tag _face _pg val = val++-- | \( O(k) \)+--   +--   List all half-edges in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> pgHalfEdges pg+-- [HalfEdge 0,HalfEdge 1,HalfEdge 2,HalfEdge 3,HalfEdge 4,HalfEdge 5]+--+-- @since 0.12.0.0+pgHalfEdges :: PlanarGraph -> [HalfEdge]+pgHalfEdges pg =+  [ he+  | he <- map HalfEdge [0 .. Vector.length (pgHalfEdgeNext pg)-1 ]+  , halfEdgeIsValid he+  ]+++-- | O(1)+--+-- @since 0.12.0.0+halfEdgeIsValid :: HalfEdge -> Bool+halfEdgeIsValid (HalfEdge eId) = eId >= 0++-- -- | O(1)+-- halfEdgeFromId :: HalfEdgeId -> HalfEdge+-- halfEdgeFromId eId = HalfEdge eId++-- -- | O(1)+-- halfEdgeId :: HalfEdge -> HalfEdgeId+-- halfEdgeId (HalfEdge eId) = eId++-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]]+-- 1711135548958680232++-- | \( O(1) \)+--+--   Query the half-edge in the pointed direction. Internal half-edges+--   are arranged clockwise and external half-edges go counter-clockwise.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> halfEdgeNext (HalfEdge 4) pg {- clockwise -}+-- HalfEdge 2+--+-- >>> halfEdgeNext (HalfEdge 3) pg {- clockwise -}+-- HalfEdge 5+--+-- >>> halfEdgeNext (HalfEdge 1) pg {- counter-clockwise -}+-- HalfEdge 11+--+-- >>> halfEdgeNext (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNext: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNext :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNext (HalfEdge eId) pg = halfEdgeCheck "halfEdgeNext" eId pg $+  HalfEdge $ pgHalfEdgeNext pg Vector.! eId++-- | \( O(1) \)+--+--   Query the half-edge opposite the pointed direction. This means counter-clockwise+--   for internal half-edges and clockwise for external half-edges.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> halfEdgePrev (HalfEdge 4) pg {- counter-clockwise -}+-- HalfEdge 6+--+-- >>> halfEdgePrev (HalfEdge 3) pg {- counter-clockwise -}+-- HalfEdge 10+--+-- >>> halfEdgePrev (HalfEdge 1) pg {- clockwise -}+-- HalfEdge 7+--+-- >>> halfEdgePrev (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgePrev: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgePrev :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgePrev (HalfEdge eId) pg = halfEdgeCheck "halfEdgePrev" eId pg $+  HalfEdge $ pgHalfEdgePrev pg Vector.! eId++-- | \( O(1) \)+--+--   Next half-edge with the same vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- @HalfEdge 0@ is poiting out from @Vertex 1@. Moving counter-clockwise+-- around @Vertex 1@ yields @HalfEdge 11@ and @HalfEdge 3@.+--+-- >>> halfEdgeNextOutgoing (HalfEdge 0) pg+-- HalfEdge 11+--+-- >>> halfEdgeNextOutgoing (HalfEdge 11) pg+-- HalfEdge 3+--+-- >>> halfEdgeNextOutgoing (HalfEdge 3) pg+-- HalfEdge 0+--+-- >>> halfEdgeNextOutgoing (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNextOutgoing: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNextOutgoing :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNextOutgoing e pg = halfEdgeCheck "halfEdgeNextOutgoing" (halfEdgeId e) pg $+  halfEdgeNext (halfEdgeTwin e) pg++-- | \( O(1) \)+--+--   Next half-edge with the same vertex in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- @HalfEdge 6@ is poiting towards @Vertex 3@. Moving clockwise+-- around @Vertex 3@ yields @HalfEdge 11@ and @HalfEdge 3@.+--+-- >>> halfEdgeNextIncoming (HalfEdge 6) pg+-- HalfEdge 5+--+-- >>> halfEdgeNextIncoming (HalfEdge 5) pg+-- HalfEdge 9+--+-- >>> halfEdgeNextIncoming (HalfEdge 9) pg+-- HalfEdge 6+--+-- >>> halfEdgeNextIncoming (HalfEdge 12) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeNextIncoming: Out-of-bounds half-edge access: 12+-- ...+--+-- @since 0.12.0.0+halfEdgeNextIncoming :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNextIncoming e pg = halfEdgeCheck "halfEdgeNextIncoming" (halfEdgeId e) pg $+  halfEdgeTwin (halfEdgeNext e pg)++-- | \( O(1) \)+--+-- @+-- 'halfEdgeTwin' . 'halfEdgeTwin' == id+-- @+--+-- @since 0.12.0.0+halfEdgeTwin :: HalfEdge -> HalfEdge+halfEdgeTwin (HalfEdge idx) = HalfEdge (idx `xor` 1)+++-- | \( O(1) \)+--+--   Tail-end of a half-edge. Synonym of 'halfEdgeTailVertex'.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeVertex (HalfEdge 1) pg+-- Vertex 0+--+-- >>> halfEdgeVertex (HalfEdge 2) pg+-- Vertex 2+--+-- >>> halfEdgeVertex (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeVertex: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeVertex :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeVertex (HalfEdge idx) pg = halfEdgeCheck "halfEdgeVertex" idx pg $+  Vertex $ pgHalfEdgeVertex pg Vector.! idx++-- | O(1)+--+--   Tail-end of a half-edge. Synonym of 'halfEdgeVertex'.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeTailVertex (HalfEdge 1) pg+-- Vertex 0+--+-- >>> halfEdgeTailVertex (HalfEdge 2) pg+-- Vertex 2+--+-- @since 0.12.0.0+halfEdgeTailVertex :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeTailVertex e pg = halfEdgeVertex e pg++-- | O(1)+--+--   Tip-end of a half-edge. This is the tail-end vertex of the twin half-edge.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeTipVertex (HalfEdge 1) pg+-- Vertex 1+--+-- >>> halfEdgeTipVertex (HalfEdge 5) pg+-- Vertex 0+--+-- @since 0.12.0.0+halfEdgeTipVertex  :: HalfEdge -> PlanarGraph -> Vertex+halfEdgeTipVertex e pg = halfEdgeVertex (halfEdgeTwin e) pg++-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden+--+-- >>> hash $ pgFromFaces [[0,1,2]]+-- 2959979592048325618++-- | \( O(1) \)+--+--   Query the face of a half-edge.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeFace (HalfEdge 0) pg+-- Face 0+--+-- >>> halfEdgeFace (HalfEdge 1) pg+-- Boundary 0+--+-- >>> halfEdgeFace (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeFace: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeFace       :: HalfEdge -> PlanarGraph -> Face+halfEdgeFace (HalfEdge eId) pg = halfEdgeCheck "halfEdgeFace" eId pg $+  faceFromId $ pgHalfEdgeFace pg Vector.! eId++-- | \( O(1) \)+--+--   Check if a half-edge's face is on a boundary.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeIsBoundary (HalfEdge 0) pg+-- False+--+-- >>> halfEdgeIsBoundary (HalfEdge 1) pg+-- True+--+-- >>> halfEdgeIsBoundary (HalfEdge 2) pg+-- False+--+-- >>> halfEdgeIsBoundary (HalfEdge 3) pg+-- True+--+-- >>> halfEdgeIsBoundary (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeIsBoundary: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeIsBoundary :: HalfEdge -> PlanarGraph -> Bool+halfEdgeIsBoundary edge pg = halfEdgeCheck "halfEdgeIsBoundary" (halfEdgeId edge) pg $+  faceIsBoundary $ halfEdgeFace edge pg++-- | \( O(1) \)+--+--   Check if a half-edge's face is interior.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> halfEdgeIsInterior (HalfEdge 0) pg+-- True+--+-- >>> halfEdgeIsInterior (HalfEdge 1) pg+-- False+--+-- >>> halfEdgeIsInterior (HalfEdge 2) pg+-- True+--+-- >>> halfEdgeIsInterior (HalfEdge 3) pg+-- False+--+-- >>> halfEdgeIsInterior (HalfEdge 6) pg+-- ... Exception: Data.PlanarGraph.Immutable.halfEdgeIsInterior: Out-of-bounds half-edge access: 6+-- ...+--+-- @since 0.12.0.0+halfEdgeIsInterior :: HalfEdge -> PlanarGraph -> Bool+halfEdgeIsInterior edge pg = halfEdgeCheck "halfEdgeIsInterior" (halfEdgeId edge) pg $+  faceIsInterior $ halfEdgeFace edge pg++-------------------------------------------------------------------------------+-- Faces++-- | \( O(k) \)+--   +--   List all faces in a graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> pgFaces pg+-- [Face 0,Face 1,Face 2,Face 3,Face 4,Face 5]+--+-- @since 0.12.0.0+pgFaces :: PlanarGraph -> [Face]+pgFaces pg =+  [ Face fId+  | fId <- [0 .. Vector.length (pgFaceEdges pg)-1 ]+  , halfEdgeIsValid (faceHalfEdge (Face fId) pg)+  ]++-- | \( O(k) \)+--   +--   List all boundaries (ie external faces) in a graph. There may be+--   multiple boundaries and they may or may not be reachable from each other.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,4,1],[0,1,2],[4,3,1],[4,5,3],[3,5,2],[2,5,0]]+--+-- <<docs/Data/PlanarGraph/planargraph-2635031442529484236.compact.svg>>+--+-- >>> pgBoundaries pg+-- [Boundary 0,Boundary 1]+--+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 4,Vertex 5]+--+-- >>> faceBoundary (Boundary 1) pg+-- [Vertex 1,Vertex 2,Vertex 3]+--+-- @since 0.12.0.0+pgBoundaries :: PlanarGraph -> [Face]+pgBoundaries pg =+  [ Boundary fId+  | fId <- [0 .. Vector.length (pgBoundaryEdges pg)-1 ]+  , halfEdgeIsValid (faceHalfEdge (Boundary fId) pg)+  ]++-- | O(1)+faceCheck :: String -> Face -> PlanarGraph -> a -> a+faceCheck tag (Face fId) pg _val+  | fId >= Vector.length (pgFaceEdges pg) || fId < 0 =+    panic tag ("Out-of-bounds face access: " ++ show fId)+  | pgFaceEdges pg Vector.! fId < 0 =+    panic tag ("Tried to access deleted face: " ++ show fId)+faceCheck tag (Boundary fId) pg _val+  | fId >= Vector.length (pgBoundaryEdges pg) || fId < 0 =+    panic tag ("Out-of-bounds boundary access: " ++ show fId)+  | pgBoundaryEdges pg Vector.! fId < 0 =+    panic tag ("Tried to access deleted boundary: " ++ show fId)+faceCheck _tag _face _pg val = val++-- | \( O(1) \)+--+--   Returns @True@ iff a face or boundary is part of the planar graph.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2]]+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> faceMember (Face 0) pg+-- True+--+-- >>> faceMember (Face 1) pg+-- False+--+-- >>> faceMember (Face 100) pg+-- False+--+-- >>> faceMember (Face (-100)) pg+-- False+--+-- >>> faceMember (Boundary 0) pg+-- True+--+-- >>> faceMember (Boundary 1) pg+-- False+--+-- @since 0.12.0.0+faceMember :: Face -> PlanarGraph -> Bool+faceMember face@(Face fId) pg =+  fId < Vector.length (pgFaceEdges pg) &&+  fId >= 0 &&+  halfEdgeIsValid (faceHalfEdge face pg)+faceMember face@(Boundary fId) pg =+  fId < Vector.length (pgFaceEdges pg) &&+  fId >= 0 &&+  halfEdgeIsValid (faceHalfEdge face pg)+++-- -- | O(1)+-- faceInvalid :: Face+-- faceInvalid = faceFromId maxBound++-- -- | O(1)+-- faceIsValid :: Face -> Bool+-- faceIsValid = not . faceIsInvalid++-- -- | O(1)+-- faceIsInvalid :: Face -> Bool+-- faceIsInvalid (Face fId)     = fId == maxBound+-- faceIsInvalid (Boundary fId) = fId == maxBound++-- | O(1)+--+-- @since 0.12.0.0+faceFromId :: FaceId -> Face+faceFromId fId | fId < 0 = Boundary (negate fId - 1)+faceFromId fId = Face fId++-- | \( O(1) \)+--+--   Maps interior faces to positive integers and boundary faces to negative integers.+--+-- ==== __Examples:__+--+-- >>> faceId (Face 0)+-- 0+--+-- >>> faceId (Face 10)+-- 10+--+-- >>> faceId (Boundary 0)+-- -1+--+-- >>> faceId (Boundary 10)+-- -11+--+-- @since 0.12.0.0+faceId :: Face -> FaceId+faceId (Face fId)     = fId+faceId (Boundary fId) = negate fId - 1+++-- | \( O(1) \)+--+--   Query the half-edge associated with a face or boundary.+--+-- ==== __Examples:__+--+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceHalfEdge (Face 0) pg+-- HalfEdge 0+--+-- >>> faceHalfEdge (Face 1) pg+-- HalfEdge 8+--+-- >>> faceHalfEdge (Boundary 0) pg+-- HalfEdge 1+--+-- >>> faceHalfEdge (Face 10) pg {- Invalid face -}+-- ... Exception: Data.PlanarGraph.Immutable.faceHalfEdge: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceHalfEdge :: Face -> PlanarGraph -> HalfEdge+faceHalfEdge face pg = faceCheck "faceHalfEdge" face pg $+  case face of+    Face fId     -> HalfEdge $ pgFaceEdges pg Vector.! fId+    Boundary fId -> HalfEdge $ pgBoundaryEdges pg Vector.! fId++-- | \( O(1) \)+--+--   Returns @True@ iff a face is interior. Does not check if the face actually exists.+--+-- ==== __Examples:__+--+-- >>> faceIsInterior (Face 0)+-- True+--+-- >>> faceIsInterior (Face 10000)+-- True+--+-- >>> faceIsInterior (Boundary 0)+-- False+--+-- @since 0.12.0.0+faceIsInterior :: Face -> Bool+faceIsInterior = not . faceIsBoundary++-- | \( O(1) \)+--+--   Returns @True@ iff a face is a boundary. Does not check if the face actually exists.+--+-- ==== __Examples:__+--+-- >>> faceIsBoundary (Face 0)+-- False+--+-- >>> faceIsBoundary (Face 10000)+-- False+--+-- >>> faceIsBoundary (Boundary 0)+-- True+--+-- @since 0.12.0.0+faceIsBoundary :: Face -> Bool+faceIsBoundary Face{}     = False+faceIsBoundary Boundary{} = True++-- faceVertices         :: Face -> ST s (CircularVector Vertex)++-- | \( O(k) \)+--+--   Query the half-edges around a face in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceHalfEdges (Face 0) pg+-- [HalfEdge 0,HalfEdge 2,HalfEdge 4,HalfEdge 6]+--+-- >>> faceHalfEdges (Face 1) pg+-- [HalfEdge 8,HalfEdge 5,HalfEdge 3,HalfEdge 10]+--+-- >>> faceHalfEdges (Boundary 0) pg+-- [HalfEdge 1,HalfEdge 11,HalfEdge 9,HalfEdge 7]+--+-- >>> faceHalfEdges (Face 10) pg+-- ... Exception: Data.PlanarGraph.Immutable.faceHalfEdges: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceHalfEdges        :: Face -> PlanarGraph -> [HalfEdge]+faceHalfEdges face pg | faceCheck "faceHalfEdges" face pg False = undefined+faceHalfEdges face pg+  | faceIsBoundary face = first : build (worker halfEdgeNext (halfEdgeNext first pg))+  | otherwise           = first : build (worker halfEdgePrev (halfEdgePrev first pg))+  where+    first = faceHalfEdge face pg+    worker :: (HalfEdge -> PlanarGraph -> HalfEdge) -> HalfEdge -> (HalfEdge -> b -> b) -> b -> b+    worker advance he cons nil+      | he == first = nil+      | otherwise   = cons he (worker advance (advance he pg) cons nil)++-- | \( O(k) \)+--+--   Query the vertices of a face in counter-clockwise order.+--+-- ==== __Examples:__+-- >>> let pg = pgFromFaces [[0,1,2,3],[4,3,2,1]]+--+-- <<docs/Data/PlanarGraph/planargraph-1711135548958680232.svg>>+--+-- >>> faceBoundary (Face 0) pg+-- [Vertex 1,Vertex 2,Vertex 3,Vertex 0]+--+-- >>> faceBoundary (Face 1) pg+-- [Vertex 3,Vertex 2,Vertex 1,Vertex 4]+--+-- >>> faceBoundary (Boundary 0) pg+-- [Vertex 0,Vertex 1,Vertex 4,Vertex 3]+--+-- >>> faceBoundary (Face 10) pg+-- ... Exception: Data.PlanarGraph.Immutable.faceBoundary: Out-of-bounds face access: 10+-- ...+--+-- @since 0.12.0.0+faceBoundary :: Face -> PlanarGraph -> [Vertex]+faceBoundary face pg = faceCheck "faceBoundary" face pg $+  map (`halfEdgeVertex` pg) $ faceHalfEdges face pg++-- faceAdjacentFaces    :: Face -> ST s (CircularVector Face)++-------------------------------------------------------------------------------+-- Mutation++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgMutate :: PlanarGraph -> (forall s. Mut.PlanarGraph s -> ST s ()) -> PlanarGraph+pgMutate pg action = runST $ do+  mutPG <- pgThaw pg+  action mutPG+  pgUnsafeFreeze mutPG++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgCreate :: (forall s. ST s (Mut.PlanarGraph s)) -> PlanarGraph+pgCreate action = runST (action >>= pgUnsafeFreeze)++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgThaw :: PlanarGraph -> ST s (Mut.PlanarGraph s)+pgThaw pg = do+  pgNextHalfEdgeId <- newSTRef $ Vector.length (pgHalfEdgeNext pg) `div` 2+  pgNextVertexId <- newSTRef $ Vector.length $ pgVertexEdges pg+  pgNextFaceId <- newSTRef $ Vector.length $ pgFaceEdges pg+  pgNextBoundaryId <- newSTRef $ Vector.length $ pgBoundaryEdges pg++  pgHalfEdgeNext   <- Mut.thawVector $ pgHalfEdgeNext pg+  pgHalfEdgePrev   <- Mut.thawVector $ pgHalfEdgePrev pg+  pgHalfEdgeFace   <- Mut.thawVector $ pgHalfEdgeFace pg+  pgHalfEdgeVertex <- Mut.thawVector $ pgHalfEdgeVertex pg+  pgVertexEdges <- Mut.thawVector $ pgVertexEdges pg+  pgFaceEdges <- Mut.thawVector $ pgFaceEdges pg+  pgBoundaryEdges <- Mut.thawVector $ pgBoundaryEdges pg+  pure Mut.PlanarGraph {..}++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgUnsafeThaw :: PlanarGraph -> ST s (Mut.PlanarGraph s)+pgUnsafeThaw pg = do+  pgNextHalfEdgeId <- newSTRef $ Vector.length $ pgHalfEdgeNext pg+  pgNextVertexId <- newSTRef $ Vector.length $ pgVertexEdges pg+  pgNextFaceId <- newSTRef $ Vector.length $ pgFaceEdges pg+  pgNextBoundaryId <- newSTRef $ Vector.length $ pgBoundaryEdges pg++  pgHalfEdgeNext   <- Mut.unsafeThawVector $ pgHalfEdgeNext pg+  pgHalfEdgePrev   <- Mut.unsafeThawVector $ pgHalfEdgePrev pg+  pgHalfEdgeFace   <- Mut.unsafeThawVector $ pgHalfEdgeFace pg+  pgHalfEdgeVertex <- Mut.unsafeThawVector $ pgHalfEdgeVertex pg+  pgVertexEdges <- Mut.unsafeThawVector $ pgVertexEdges pg+  pgFaceEdges <- Mut.unsafeThawVector $ pgFaceEdges pg+  pgBoundaryEdges <- Mut.unsafeThawVector $ pgBoundaryEdges pg+  pure Mut.PlanarGraph {..}++-- | \( O(n) \)+--+-- @since 0.12.0.0+pgFreeze :: Mut.PlanarGraph s -> ST s PlanarGraph+pgFreeze pg = do+  maxEdgeId <- readSTRef (Mut.pgNextHalfEdgeId pg)+  maxVertexId <- readSTRef (Mut.pgNextVertexId pg)+  maxFaceId <- readSTRef (Mut.pgNextFaceId pg)+  maxBoundaryId <- readSTRef (Mut.pgNextBoundaryId pg)++  pgHalfEdgeNext   <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeNext pg)+  pgHalfEdgePrev   <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgePrev pg)+  pgHalfEdgeFace   <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeFace pg)+  pgHalfEdgeVertex <- Vector.take (maxEdgeId*2) <$> Mut.freezeVector (Mut.pgHalfEdgeVertex pg)+  pgVertexEdges <- Vector.take maxVertexId <$> Mut.freezeVector (Mut.pgVertexEdges pg)+  pgFaceEdges <- Vector.take maxFaceId <$> Mut.freezeVector (Mut.pgFaceEdges pg)+  pgBoundaryEdges <- Vector.take maxBoundaryId <$> Mut.freezeVector (Mut.pgBoundaryEdges pg)+  pure PlanarGraph { .. }++-- | \( O(1) \)+--+-- @since 0.12.0.0+pgUnsafeFreeze :: Mut.PlanarGraph s -> ST s PlanarGraph+pgUnsafeFreeze pg = do+  maxEdgeId <- readSTRef (Mut.pgNextHalfEdgeId pg)+  maxVertexId <- readSTRef (Mut.pgNextVertexId pg)+  maxFaceId <- readSTRef (Mut.pgNextFaceId pg)+  maxBoundaryId <- readSTRef (Mut.pgNextBoundaryId pg)++  pgHalfEdgeNext   <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeNext pg)+  pgHalfEdgePrev   <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgePrev pg)+  pgHalfEdgeFace   <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeFace pg)+  pgHalfEdgeVertex <- Vector.take (maxEdgeId*2) <$> Mut.unsafeFreezeVector (Mut.pgHalfEdgeVertex pg)+  pgVertexEdges <- Vector.take maxVertexId <$> Mut.unsafeFreezeVector (Mut.pgVertexEdges pg)+  pgFaceEdges <- Vector.take maxFaceId <$> Mut.unsafeFreezeVector (Mut.pgFaceEdges pg)+  pgBoundaryEdges <- Vector.take maxBoundaryId <$> Mut.unsafeFreezeVector (Mut.pgBoundaryEdges pg)+  pure PlanarGraph { .. }++-------------------------------------------------------------------------------+-- Tutte embedding++-- | \( O(n^3) \)+--+-- @since 0.12.0.0+tutteEmbedding :: PlanarGraph -> Vector.Vector (V2 Double)+tutteEmbedding pg = runST $ do+  let nVertices = Vector.length (pgVertexEdges pg)+  -- trace ("nVertices: " ++ show nVertices) $ return ()+  m <- Vector.replicateM nVertices (V.replicate nVertices 0)+  vx <- V.replicate nVertices 0+  vy <- V.replicate nVertices 0++  let boundary = faceBoundary (Boundary 0) pg+  let nBoundary = length boundary+  -- trace ("Vectors: " ++ show boundary) $+  forM_ (zip boundary (regularPolygon nBoundary)) $ \(vertex,(x,y)) -> do+    let valid = halfEdgeIsValid $ vertexHalfEdge vertex pg+    when valid $ do+      V.write (m Vector.! vertexId vertex) (vertexId vertex) (1::Double)+      V.write vx (vertexId vertex) x+      V.write vy (vertexId vertex) y++  forM_ [0..nVertices-1] $ \vId -> -- trace ("Vertex: " ++ show vId) $+    do+      let valid = halfEdgeIsValid $ vertexHalfEdge (Vertex vId) pg+      unless valid $ do+        V.write (m Vector.! vId) vId (1::Double)+      when valid $ do+        let onOuterBoundary =+              Boundary 0 == halfEdgeFace (halfEdgeTwin $ vertexHalfEdge (Vertex vId) pg) pg+        unless onOuterBoundary $ do+          let vertex = Vertex vId+          let neighbours = vertexNeighbours vertex pg+          forM_ neighbours $ \neighbour ->+            V.write (m Vector.! vId) (vertexId neighbour) (1::Double)+          V.write (m Vector.! vId) vId (negate $ fromIntegral $ length neighbours)++  mi <- mapM Vector.freeze m+  vxi <- Vector.freeze vx+  vyi <- Vector.freeze vy++  let xPos = reifyMatrix mi vxi luSolve+      yPos = reifyMatrix mi vyi luSolve++  pure $ Vector.zipWith V2 xPos yPos++reifyMatrix :: forall a. Vector.Vector (Vector.Vector a) ->+  Vector.Vector a ->+  (forall (n :: *). Dim n => V n (V n a) -> V n a -> V n a) ->+  Vector.Vector a+reifyMatrix m v f = reifyDim (Vector.length m) $ \(Proxy :: Proxy n) ->+  toVector (f (coerce m :: (V n (V n a))) (coerce v))++regularPolygon :: Int -> [(Double, Double)]+regularPolygon n =+    [ (cos ang, sin ang)+    | i <- [0 .. n-1]+    , let ang = fromIntegral i * frac + pi/2]+  where+    frac = 2*pi / fromIntegral n
+ src/Data/PlanarGraph/Internal.hs view
@@ -0,0 +1,92 @@+module Data.PlanarGraph.Internal where++import           Control.Monad.ST+import           Data.STRef+import qualified Data.Vector          as V (unsafeFreeze)+import qualified Data.Vector          as Vector+import           Data.Vector.Circular (CircularVector)+import qualified Data.Vector.Circular as CV+import           Data.Vector.Mutable  (STVector)+import qualified Data.Vector.Mutable  as V++-------------------------------------------------------------------------------+-- Resizeable vector++type GrowVector s v = STRef s (STVector s v)++newVector :: Int -> ST s (GrowVector s v)+newVector n = newSTRef =<< V.new n++setVector :: GrowVector s v -> v -> ST s ()+setVector ref val = do+  vec <- readSTRef ref+  V.set vec val++readVector :: GrowVector s v -> Int -> ST s v+readVector ref idx = do+  v <- readSTRef ref+  V.read v idx++writeVector :: GrowVector s v -> Int -> v -> ST s ()+writeVector ref idx val = do+  v <- readSTRef ref+  let l = V.length v+  if idx >= l+    then {-trace ("Growing: " ++ show (idx, l)) $ -} do+      v' <- V.grow v ((idx+1)*2)+      V.write v' idx val+      writeSTRef ref v'+    else -- trace ("Writing: " ++ show (idx, l)) $+      V.write v idx val++freezeVector :: GrowVector s v -> ST s (Vector.Vector v)+freezeVector ref = Vector.freeze =<< readSTRef ref++unsafeFreezeVector :: GrowVector s v -> ST s (Vector.Vector v)+unsafeFreezeVector ref = Vector.unsafeFreeze =<< readSTRef ref++thawVector :: Vector.Vector v -> ST s (GrowVector s v)+thawVector v = newSTRef =<< Vector.thaw v++unsafeThawVector :: Vector.Vector v -> ST s (GrowVector s v)+unsafeThawVector v = newSTRef =<< Vector.unsafeThaw v+++freezeCircularVector :: Int -> GrowVector s v -> ST s (CircularVector v)+freezeCircularVector n ref =+  (CV.unsafeFromVector . Vector.take n) <$> (V.unsafeFreeze =<< readSTRef ref)+++-------------------------------------------------------------------------------+-- Planar graph++type EdgeId = Int+type HalfEdgeId = Int+type VertexId = Int++-- | Numerical face identifier. Negative numbers indicate boundaries, non-negative numbers+--   are internal faces.+type FaceId = Int++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.++-- FIXME: Use STRefU ?+-- PlanarGraph with 0 vertices: No edges, no vertices, no faces.+-- PlanarGraph with 1 vertex: No edges, no interior faces.+-- PlanarGraph with 2 vertices: One edge, no interior faces.+-- PlanarGraph with 3+ vertices: Usual properties hold.+data PlanarGraph s = PlanarGraph+  { pgNextHalfEdgeId :: !(STRef s HalfEdgeId)+  , pgNextVertexId   :: !(STRef s VertexId)+  , pgNextFaceId     :: !(STRef s FaceId)+  , pgNextBoundaryId :: !(STRef s FaceId)+  , pgHalfEdgeNext   :: !(GrowVector s HalfEdgeId) -- HalfEdge indexed+  , pgHalfEdgePrev   :: !(GrowVector s HalfEdgeId) -- HalfEdge indexed+  , pgHalfEdgeVertex :: !(GrowVector s VertexId)   -- HalfEdge indexed+  , pgHalfEdgeFace   :: !(GrowVector s FaceId)     -- HalfEdge indexed+  , pgVertexEdges    :: !(GrowVector s HalfEdgeId) -- Vertex indexed+  , pgFaceEdges      :: !(GrowVector s HalfEdgeId) -- Face indexed+  , pgBoundaryEdges  :: !(GrowVector s HalfEdgeId) -- Boundary faces+  } deriving Eq+
+ src/Data/PlanarGraph/Mutable.hs view
@@ -0,0 +1,692 @@+module Data.PlanarGraph.Mutable+  ( -- * Planar graphs+    PlanarGraph+  , pgFromFaces   -- :: [[VertexId]] -> ST s (PlanarGraph s)+  , pgFromFacesCV -- :: [CircularVector VertexId] -> ST s (PlanarGraph s)+  , pgClone       -- :: PlanarGraph s -> ST s (PlanarGraph s)+  , pgHash        -- :: PlanarGraph s -> ST s Int++    -- * Elements+    -- ** Vertices+  , Vertex, VertexId+  , vertexFromId                -- :: VertexId -> PlanarGraph s -> Vertex s+  , vertexToId                  -- :: Vertex s -> VertexId+  , vertexHalfEdge              -- :: Vertex s -> ST s (HalfEdge s)+  , vertexIsBoundary            -- :: Vertex s -> ST s Bool+  , vertexOutgoingHalfEdges     -- :: Vertex s -> ST s (CircularVector (HalfEdge s))+  , vertexWithOutgoingHalfEdges -- :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+  , vertexIncomingHalfEdges     -- :: Vertex s -> ST s (CircularVector (HalfEdge s))+  , vertexWithIncomingHalfEdges -- :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+  , vertexNeighbours            -- :: Vertex s -> ST s (CircularVector (Vertex s))+  -- , vertexNew -- :: PlanarGraph s -> ST s (Vertex s)+  -- , vertexSetHalfEdge -- :: Vertex s -> HalfEdge s -> ST s ()++    -- ** Edges+  , Edge, EdgeId+  , edgeFromId           -- :: EdgeId -> PlanarGraph s -> Edge s+  , edgeToId             -- :: Edge s -> EdgeId+  , edgeFromHalfEdge     -- :: HalfEdge s -> Edge s++    -- ** Half-edges+  , HalfEdge, HalfEdgeId+  , halfEdgeFromId       -- :: HalfEdgeId -> PlanarGraph s -> HalfEdge s+  , halfEdgeToId         -- :: HalfEdge s -> HalfEdgeId+  , halfEdgeNext         -- :: HalfEdge s -> ST s (HalfEdge s)+  , halfEdgePrev         -- :: HalfEdge s -> ST s (HalfEdge s)+  , halfEdgeNextOutgoing -- :: HalfEdge s -> ST s (HalfEdge s)+  , halfEdgeNextIncoming -- :: HalfEdge s -> ST s (HalfEdge s)+  , halfEdgeVertex       -- :: HalfEdge s -> ST s (Vertex s)+  , halfEdgeTwin         -- :: HalfEdge s -> HalfEdge s+  , halfEdgeTailVertex   -- :: HalfEdge s -> ST s (Vertex s)+  , halfEdgeTipVertex    -- :: HalfEdge s -> ST s (Vertex s)+  , halfEdgeFace         -- :: HalfEdge s -> ST s (Face s)+  , halfEdgeIsInterior   -- :: HalfEdge s -> ST s Bool+  -- , halfEdgeNew          -- :: PlanarGraph s -> ST s (HalfEdge s)+  -- , halfEdgeSetNext      -- :: HalfEdge s -> HalfEdge s -> ST s ()+  -- , halfEdgeSetPrev      -- :: HalfEdge s -> HalfEdge s -> ST s ()+  -- , halfEdgeSetFace      -- :: HalfEdge s -> Face s -> ST s ()+  -- , halfEdgeSetVertex    -- :: HalfEdge s -> Vertex s -> ST s ()++    -- ** Faces+  , Face, FaceId+  , faceInvalid    -- :: PlanarGraph s -> Face s+  , faceIsValid    -- :: Face s -> Bool+  , faceIsInvalid  -- :: Face s -> Bool+  , faceFromId     -- :: FaceId -> PlanarGraph s -> Face s+  , faceToId       -- :: Face s -> FaceId+  , faceHalfEdge   -- :: Face s -> ST s (HalfEdge s)+  , faceIsInterior -- :: Face s -> Bool+  , faceIsBoundary -- :: Face s -> Bool+  , faceHalfEdges  -- :: Face s -> ST s (CircularVector (HalfEdge s))+  , faceBoundary   -- :: Face s -> ST s (CircularVector (Vertex s))+  -- , faceNew :: PlanarGraph s -> ST s (Face s)+  -- , faceNewBoundary :: PlanarGraph s -> ST s (Face s)+  -- , faceSetHalfEdge :: Face s -> HalfEdge s -> ST s ()++    -- * Mutation+  , pgConnectVertices -- :: HalfEdge s -> HalfEdge s -> ST s (Edge s)+-- pgSplitHalfEdge :: HalfEdge s -> ST s (Vertex s)++-- pgRemoveFace :: Face s -> ST s ()+-- pgRemoveHalfEdge :: HalfEdge s -> ST s ()+-- pgRemoveVertex :: Vertex s -> ST s ()+    -- * Misc+  -- , tutteEmbedding -- :: PlanarGraph s -> ST s (Vector.Vector (Double, Double))+  )+  where++import           Control.Monad             (forM_, unless, when)+import           Control.Monad.ST          (ST)+import           Data.Bits                 (Bits (xor))+import qualified Data.HashMap.Strict       as HM+import           Data.Hashable             (Hashable (hashWithSalt))+import           Data.PlanarGraph.Internal+import           Data.STRef                (modifySTRef', newSTRef, readSTRef, writeSTRef)+import           Data.Vector.Circular      (CircularVector)+import qualified Data.Vector.Circular      as CV++import Debug.Trace++-------------------------------------------------------------------------------+-- Elements: Half-edges, vertices, faces.++data HalfEdge s = HalfEdge HalfEdgeId (PlanarGraph s)+  deriving Eq+instance Show (HalfEdge s) where+  showsPrec d (HalfEdge s _) = showsPrec d s+instance Hashable (HalfEdge s) where+  hashWithSalt salt (HalfEdge eId _) = hashWithSalt salt eId+++data Edge s = Edge EdgeId (PlanarGraph s)+  deriving Eq++data Vertex s = Vertex VertexId (PlanarGraph s)+  deriving Eq+instance Show (Vertex s) where+  showsPrec d (Vertex v _) = showsPrec d v+instance Hashable (Vertex s) where+  hashWithSalt salt (Vertex vId _) = hashWithSalt salt vId++data Face s = Face FaceId (PlanarGraph s) | Boundary FaceId (PlanarGraph s)+  deriving Eq+instance Show (Face s) where+  showsPrec _ (Face fId _)     = showString "Face " . shows fId+  showsPrec _ (Boundary fId _) = showString "Boundary " . shows fId++-------------------------------------------------------------------------------+-- Planar graph++panic :: String -> String -> a+panic tag msg = error $ "Data.PlanarGraph.Mutable." ++ tag ++ ": " ++ msg++eqCheck :: String -> PlanarGraph s -> PlanarGraph s -> a -> a+eqCheck tag pg1 pg2 v+  | pg1 == pg2 = v+  | otherwise = panic tag "Invalid cross reference."++empty :: Int -> Int -> Int -> ST s (PlanarGraph s)+empty nFaces nVertices nEdges = PlanarGraph+  <$> newSTRef 0+  <*> newSTRef 0+  <*> newSTRef 0+  <*> newSTRef 0+  <*> newVector (nEdges*2)+  <*> newVector (nEdges*2)+  <*> newVector (nEdges*2)+  <*> newVector (nEdges*2)+  <*> newVector nVertices+  <*> newVector nFaces+  <*> newVector 0++-- {-+--   For all boundary vertices:+--     vertex.half-edge.face == interior+--     vertex.half-edge.twin.face == exterior+--   Boundary face: 0++--   create N+-- -}+-- -- | O(n)+-- --   Create a planar graph with N boundary vertices.+-- new :: Int -> ST s (PlanarGraph s)+-- new n | n < 0 = panic "new" "Cannot contain negative vertices."+-- new 0 = empty 0 0 0+-- new 1 = undefined+-- new 2 = undefined+-- new n = pgFromFaces [[0..n-1]]++-- $setup+--+-- >>> import Control.Monad.ST++-- Disabled since hashes are not stable across different versions of hashable.+-- >>> runST $ pgFromFaces [[0,1,2]] >>= pgHash+-- 2959979592048325618+-- >>> runST $ pgFromFaces [[0,1,2,3]] >>= pgHash+-- 2506803680640023584+-- >>> runST $ pgFromFaces [[0,1,2,3],[4,3,2,1]] >>= pgHash+-- 1711135548958680232++-- | \( O(n \log n) \)+--+--+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+pgFromFaces :: [[VertexId]] -> ST s (PlanarGraph s)+pgFromFaces = pgFromFacesCV . map CV.unsafeFromList++pgFromFacesCV :: [CircularVector VertexId] -> ST s (PlanarGraph s)+pgFromFacesCV [] = empty 0 0 0+pgFromFacesCV faces = do+  let maxVertexId = maximum (map CV.maximum faces)+      nFaces = length faces+      nHalfEdges = sum (map length faces)+  pg <- empty nFaces (maxVertexId+1) (nHalfEdges `div` 2)+  setVector (pgVertexEdges pg) (-1)+  writeSTRef (pgNextVertexId pg) (maxVertexId+1)+  edgeMap <- newSTRef HM.empty+  let getHalfEdge (vTail, vTip) = do+        hm <- readSTRef edgeMap+        case HM.lookup (vTail, vTip) hm of+          Just{} -> panic "fromFaces" "Duplicate half-edge."+          Nothing ->+            case HM.lookup (vTip, vTail) hm of+              Just twin -> pure (halfEdgeTwin twin)+              Nothing   -> {-trace ("Creating new half-edge: " ++ show (vTip, vTail)) $ -} do+                halfEdge <- halfEdgeNew pg+                halfEdgeSetFace (halfEdgeTwin halfEdge) (faceInvalid pg)+                vertexSetHalfEdge (vertexFromId vTip pg) halfEdge+                writeSTRef edgeMap $ HM.insert (vTail, vTip) halfEdge hm+                halfEdgeSetVertex halfEdge (vertexFromId vTip pg)+                halfEdgeSetVertex (halfEdgeTwin halfEdge) (vertexFromId vTail pg)+                pure halfEdge+      addFace face | length face < 3 = panic "fromFaces" "Faces must have at least 3 vertices."+      addFace face = {- trace "Adding face" $ -} do+        fId <- faceNew pg+        let edges = CV.zip face (CV.rotateRight 1 face)+        halfEdges <- {- trace ("getHalfEdge") $ -} mapM getHalfEdge edges+        faceSetHalfEdge fId (CV.head halfEdges)+        setNextPrevFace fId (CV.reverse halfEdges)+  forM_ faces addFace++  maxHalfEdgeId <- readSTRef (pgNextHalfEdgeId pg)+  -- For each half-edge:+  --   If face is invalid:+  --     Find loop and add it as a boundary.+  forM_ (map (`halfEdgeFromId` pg) [0..maxHalfEdgeId*2-1]) $ \he -> {- trace ("Scan halfedge: " ++ show he) $ -} do+    -- f <- halfEdgeFace he+    validFace <- faceIsValid <$> halfEdgeFace he+    unless validFace $ {- trace ("Found invalid face: " ++ show f) $ -} do+      face <- faceNewBoundary pg+      boundary <- halfEdgeConstructBoundary he+      -- trace ("Boundary: " ++ show (face, boundary)) $ return ()+      faceSetHalfEdge face (CV.head boundary)+      setNextPrevFace face boundary+  pure pg+  where+    setNextPrevFace fId halfEdges = do+      let edgeTriples = CV.zip3 (CV.rotateLeft 1 halfEdges) halfEdges (CV.rotateRight 1 halfEdges)+      forM_ (edgeTriples) $ \(prev, edge, next) -> do+          halfEdgeSetNext edge next+          halfEdgeSetPrev edge prev+          halfEdgeSetFace edge fId++-- fromFaces' :: Int -> Int -> Int -> [CircularVector VertexId] -> ST s (PlanarGraph s)+-- fromFaces' nFaces nHalfEdges maxVertexId faces = do+--   undefined++-- | \( O(n) \)+pgClone :: PlanarGraph s -> ST s (PlanarGraph s)+pgClone = undefined++-- dualTree :: Face s -> ST s (Tree (Face s))+-- dualTree = undefined++pgHash :: PlanarGraph s -> ST s Int+pgHash pg = do+  eMax <- readSTRef (pgNextHalfEdgeId pg)+  let loop [] salt = pure salt+      loop (edgeId:rest) salt = do+        let he = halfEdgeFromId (edgeId*2) pg+        vTail <- halfEdgeTailVertex he+        vTip <- halfEdgeTipVertex he+        loop rest (hashWithSalt salt (vTail, vTip))+  abs <$> loop [0..eMax-1] 0++-------------------------------------------------------------------------------+-- Vertices++-- | \( O(1) \)+vertexFromId :: VertexId -> PlanarGraph s -> Vertex s+vertexFromId vId pg = Vertex vId pg++-- | \( O(1) \)+vertexToId :: Vertex s -> VertexId+vertexToId (Vertex vId _pg) = vId++-- | \( O(1) \)+vertexHalfEdge :: Vertex s -> ST s (HalfEdge s)+vertexHalfEdge (Vertex vId pg) = do+  eId <- readVector (pgVertexEdges pg) vId+  pure $ HalfEdge eId pg++-- | \( O(1) \)+vertexIsBoundary :: Vertex s -> ST s Bool+vertexIsBoundary vertex = faceIsBoundary <$> (halfEdgeFace =<< (halfEdgeTwin <$> vertexHalfEdge vertex))++-- | O(k)+vertexOutgoingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))+vertexOutgoingHalfEdges vertex = do+  tmp <- newVector 10+  iRef <- newSTRef 0+  vertexWithOutgoingHalfEdges vertex $ \edge -> do+    i <- readSTRef iRef+    modifySTRef' iRef succ+    writeVector tmp i edge+  i <- readSTRef iRef+  freezeCircularVector i tmp++-- | O(k), more efficient than 'vertexOutgoingHalfEdges'.+vertexWithOutgoingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+vertexWithOutgoingHalfEdges vertex cb = do+  first <- vertexHalfEdge vertex+  cb first+  let loop edge | edge == first = return ()+      loop edge = trace ("At edge: "++ show (first, edge)) $ do+        cb edge+        loop =<< halfEdgeNext (halfEdgeTwin edge)+  loop =<< halfEdgeNext (halfEdgeTwin first)++-- | O(k)+vertexIncomingHalfEdges :: Vertex s -> ST s (CircularVector (HalfEdge s))+vertexIncomingHalfEdges vertex = CV.map halfEdgeTwin <$> vertexOutgoingHalfEdges vertex++-- | O(k)+vertexWithIncomingHalfEdges :: Vertex s -> (HalfEdge s -> ST s ()) -> ST s ()+vertexWithIncomingHalfEdges = undefined++-- | O(k)+vertexNeighbours :: Vertex s -> ST s (CircularVector (Vertex s))+vertexNeighbours vertex = CV.mapM halfEdgeVertex =<< vertexIncomingHalfEdges vertex++-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++-- -- O(1), internal function.+-- vertexNew :: PlanarGraph s -> ST s (Vertex s)+-- vertexNew pg = do+--   vId <- readSTRef (pgNextVertexId pg)+--   writeSTRef (pgNextVertexId pg) (vId+1)+--   return (Vertex vId pg)++vertexSetHalfEdge :: Vertex s -> HalfEdge s -> ST s ()+vertexSetHalfEdge (Vertex vId pg) (HalfEdge eId pg') = eqCheck "vertexSetHalfEdge" pg pg' $+  writeVector (pgVertexEdges pg) vId eId++-------------------------------------------------------------------------------+-- Edges++-- | O(1)+edgeFromId :: EdgeId -> PlanarGraph s -> Edge s+edgeFromId = Edge++-- | O(1)+edgeToId :: Edge s -> EdgeId+edgeToId (Edge e _) = e++-- | O(1)+edgeFromHalfEdge :: HalfEdge s -> Edge s+edgeFromHalfEdge (HalfEdge he pg) = Edge (he `div` 2) pg++-- -- | O(1)+-- edgeToHalfEdges :: Edge s -> (HalfEdge s, HalfEdge s)+-- edgeToHalfEdges (Edge e pg) = (HalfEdge (e*2) pg, HalfEdge (e*2+1) pg)++-------------------------------------------------------------------------------+-- Half-edges++-- | O(1)+halfEdgePlanarGraph :: HalfEdge s -> PlanarGraph s+halfEdgePlanarGraph (HalfEdge _ pg) = pg++-- -- | O(1)+-- halfEdgeIsValid :: HalfEdge s -> Bool+-- halfEdgeIsValid (HalfEdge eId _) = eId >= 0++-- | O(1)+halfEdgeFromId :: HalfEdgeId -> PlanarGraph s -> HalfEdge s+halfEdgeFromId eId pg = HalfEdge eId pg++-- | O(1)+halfEdgeToId :: HalfEdge s -> HalfEdgeId+halfEdgeToId (HalfEdge eId _pg) = eId++-- | O(1)+halfEdgeNext :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNext (HalfEdge eId pg) = do+  next <- readVector (pgHalfEdgeNext pg) eId+  pure $ HalfEdge next pg++-- | O(1)+halfEdgePrev :: HalfEdge s -> ST s (HalfEdge s)+halfEdgePrev (HalfEdge eId pg) = do+  prev <- readVector (pgHalfEdgePrev pg) eId+  pure $ HalfEdge prev pg++-- | O(1)+--   Next half-edge with the same vertex.+halfEdgeNextOutgoing :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNextOutgoing = halfEdgeNext . halfEdgeTwin++-- | O(1)+--   Next half-edge with the same vertex.+halfEdgeNextIncoming :: HalfEdge s -> ST s (HalfEdge s)+halfEdgeNextIncoming = halfEdgePrev . halfEdgeTwin++-- | O(1)+halfEdgeVertex     :: HalfEdge s -> ST s (Vertex s)+halfEdgeVertex (HalfEdge idx pg) = do+  v <- readVector (pgHalfEdgeVertex pg) idx+  pure $ Vertex v pg++-- | O(1)+halfEdgeTwin       :: HalfEdge s -> HalfEdge s+halfEdgeTwin (HalfEdge idx graph) = HalfEdge (idx `xor` 1) graph++-- | O(1)+--   Tail vertex. IE. the vertex of the twin edge.+halfEdgeTailVertex :: HalfEdge s -> ST s (Vertex s)+halfEdgeTailVertex = halfEdgeVertex++-- | O(1)+--   Synonym of `halfEdgeVertex`.+halfEdgeTipVertex  :: HalfEdge s -> ST s (Vertex s)+halfEdgeTipVertex = halfEdgeVertex . halfEdgeTwin++-- | \( O(1) \)+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; show <$> halfEdgeFace (halfEdgeFromId 0 pg)+-- "Face 0"+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; show <$> halfEdgeFace (halfEdgeFromId 1 pg)+-- "Boundary 0"+--+halfEdgeFace       :: HalfEdge s -> ST s (Face s)+halfEdgeFace (HalfEdge eId pg) = do+  fId <- readVector (pgHalfEdgeFace pg) eId+  pure $ faceFromId fId pg++-- | O(n)+--   Scan boundary half-edges without using 'next' or 'prev'.+halfEdgeConstructBoundary :: HalfEdge s -> ST s (CircularVector (HalfEdge s))+halfEdgeConstructBoundary halfEdge = {- trace ("mkBoundary from: " ++ show halfEdge) $ -} do+  tmp <- newVector 10+  writeVector tmp 0 halfEdge+  let loop i edge | edge == halfEdge = {- trace "Done" $ -} return i+      loop i edge = {- trace ("Going to: " ++ show edge) $ -} do+        face <- halfEdgeFace edge+        if faceIsInvalid face+          then do+            writeVector tmp i edge+            loop (i+1) =<< (halfEdgeTwin <$> halfEdgeNextIncoming edge)+          else+            loop i =<< (halfEdgeTwin <$> halfEdgePrev edge)+  i <- loop 1 =<< (halfEdgeTwin <$> halfEdgeNextIncoming halfEdge)+  cv <- freezeCircularVector i tmp+  -- trace ("Boundary: " ++ show cv) $ pure cv+  pure cv++-- | O(k)+halfEdgeWithLoop        :: HalfEdge s -> (HalfEdge s -> ST s ()) -> ST s ()+halfEdgeWithLoop he cb = worker =<< halfEdgeNext he+  where+    worker edge+      | edge == he = return ()+      | otherwise  = do cb edge; worker =<< halfEdgeNext edge++-- $setup+-- >>> let genPG = pgFromFaces [[0,1,2]]++-- | \( O(1) \)+--   Check if a half-edge's face is interior or exterior.+--+-- ==== __Examples:__+-- @+-- 'pgFromFaces' [[0,1,2]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2959979592048325618.svg>>+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 0 pg)+-- True+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 1 pg)+-- False+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 2 pg)+-- True+--+-- >>> runST $ do pg <- pgFromFaces [[0,1,2]]; halfEdgeIsInterior (halfEdgeFromId 3 pg)+-- False+halfEdgeIsInterior :: HalfEdge s -> ST s Bool+halfEdgeIsInterior edge = faceIsInterior <$> halfEdgeFace edge++-- O(1) Allocate new half-edge pair.+halfEdgeNew :: PlanarGraph s -> ST s (HalfEdge s)+halfEdgeNew pg = do+  eId <- readSTRef (pgNextHalfEdgeId pg)+  writeSTRef (pgNextHalfEdgeId pg) (eId+1)+  return (HalfEdge (eId*2) pg)++halfEdgeSetNext :: HalfEdge s -> HalfEdge s -> ST s ()+halfEdgeSetNext (HalfEdge e pg) (HalfEdge next pg') = eqCheck "halfEdgeSetNext" pg pg' $+  -- trace ("Set next: " ++ show (e, next)) $+  writeVector (pgHalfEdgeNext pg) e next++halfEdgeSetPrev :: HalfEdge s -> HalfEdge s -> ST s ()+halfEdgeSetPrev (HalfEdge e pg) (HalfEdge prev pg') = eqCheck "halfEdgeSetPrev" pg pg' $+  -- trace ("Set prev: " ++ show (e, prev)) $+  writeVector (pgHalfEdgePrev pg) e prev++halfEdgeSetFace :: HalfEdge s -> Face s -> ST s ()+halfEdgeSetFace (HalfEdge e pg) face =+  -- trace ("Set face: " ++ show (e, face)) $+  writeVector (pgHalfEdgeFace pg) e (faceToId face)++halfEdgeSetVertex :: HalfEdge s -> Vertex s -> ST s ()+halfEdgeSetVertex (HalfEdge e pg) vertex =+  -- trace ("Set vertex: " ++ show (e, vertex)) $+  writeVector (pgHalfEdgeVertex pg) e (vertexToId vertex)++-------------------------------------------------------------------------------+-- Faces++-- | O(1)+faceInvalid :: PlanarGraph s -> Face s+faceInvalid = faceFromId maxBound++-- | O(1)+faceIsValid :: Face s -> Bool+faceIsValid = not . faceIsInvalid++-- | O(1)+faceIsInvalid :: Face s -> Bool+faceIsInvalid (Face fId _)     = fId == maxBound+faceIsInvalid (Boundary fId _) = fId == maxBound++-- | O(1)+faceFromId :: FaceId -> PlanarGraph s -> Face s+faceFromId fId pg | fId < 0 = Boundary (negate fId - 1) pg+faceFromId fId pg = Face fId pg++-- | O(1)+faceToId :: Face s -> FaceId+faceToId (Face fId _)     = fId+faceToId (Boundary fId _) = negate fId - 1++-- | O(1)+faceHalfEdge         :: Face s -> ST s (HalfEdge s)+faceHalfEdge (Face fId pg) = do+  eId <- readVector (pgFaceEdges pg) fId+  pure $ HalfEdge eId pg+faceHalfEdge (Boundary fId pg) = do+  eId <- readVector (pgBoundaryEdges pg) fId+  pure $ HalfEdge eId pg++-- | O(1)+faceIsInterior       :: Face s -> Bool+faceIsInterior = not . faceIsBoundary++-- | O(1)+faceIsBoundary       :: Face s -> Bool+faceIsBoundary Face{}     = False+faceIsBoundary Boundary{} = True++-- faceVertices         :: Face s -> ST s (CircularVector (Vertex s))++-- | O(k)+--   Counterclockwise vector of edges.+faceHalfEdges        :: Face s -> ST s (CircularVector (HalfEdge s))+faceHalfEdges face+  | faceIsBoundary face = worker halfEdgeNext+  | otherwise           = worker halfEdgePrev+  where+    worker advance = do+      first <- faceHalfEdge face+      tmp <- newVector 10+      writeVector tmp 0 first+      let loop i edge | edge == first = return i+          loop i edge = do+            writeVector tmp i edge+            loop (i+1) =<< advance edge+      i <- loop 1 =<< advance first+      freezeCircularVector i tmp++-- | O(k)+faceBoundary :: Face s -> ST s (CircularVector (Vertex s))+faceBoundary face = CV.mapM halfEdgeVertex =<< faceHalfEdges face++-- faceAdjacentFaces    :: Face s -> ST s (CircularVector (Face s))++faceNew :: PlanarGraph s -> ST s (Face s)+faceNew pg = do+  fId <- readSTRef (pgNextFaceId pg)+  writeSTRef (pgNextFaceId pg) (fId+1)+  return (Face fId pg)++faceNewBoundary :: PlanarGraph s -> ST s (Face s)+faceNewBoundary pg = do+  fId <- readSTRef (pgNextBoundaryId pg)+  writeSTRef (pgNextBoundaryId pg) (fId+1)+  return (Boundary fId pg)++faceSetHalfEdge :: Face s -> HalfEdge s -> ST s ()+faceSetHalfEdge (Boundary fId pg) (HalfEdge eId pg') = eqCheck "faceSetHalfEdge" pg pg' $+  -- trace ("faceSetHalfEdge: " ++ show (fId, eId)) $+  writeVector (pgBoundaryEdges pg) fId eId+faceSetHalfEdge (Face fId pg) (HalfEdge eId pg') = eqCheck "faceSetHalfEdge" pg pg' $+  writeVector (pgFaceEdges pg) fId eId++-------------------------------------------------------------------------------+-- Mutation++-- | O(k) where @k@ is the number of edges in new face.+--+--   The two half-edges must be different, must have the same face, and may not be+--   consecutive. The first half-edge will stay in the original face. The second+--   half-edge will be in the newly created face.+--+-- ==== __Examples:__+--+-- @+-- 'pgFromFaces' [[0,1,2,3]]+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-2506803680640023584.svg>>+--+-- @+-- do pg <- 'pgFromFaces' [[0,1,2,3]]+--    let he0 = 'halfEdgeFromId' 0 pg'+--        he4 = 'halfEdgeFromId' 4 pg'+--    'pgConnectVertices' he0 he4+-- @+--+-- <<docs/Data/PlanarGraph/planargraph-1902492848341357096.svg>>+pgConnectVertices :: HalfEdge s -> HalfEdge s -> ST s (Edge s)+pgConnectVertices e1 e2 =+  eqCheck "pgConnectVertices" (halfEdgePlanarGraph e1) (halfEdgePlanarGraph e2) $ do+    let pg = halfEdgePlanarGraph e1+    when (e1 == e2) $ fail "Edges must be different"+    f1 <- halfEdgeFace e1+    f2 <- halfEdgeFace e2+    unless (f1==f2) $ fail "Faces must be the same"+    e1' <- halfEdgeNext e1+    e2' <- halfEdgeNext e2+    when (e1' == e2 || e2' == e1) $ fail "Edges must not be consecutive"++    e1_prev <- halfEdgePrev e1+    e2_prev <- halfEdgePrev e2++    he <- halfEdgeNew pg+    halfEdgeSetFace he f1+    let he' = halfEdgeTwin he+    +    halfEdgeSetVertex he =<< halfEdgeVertex e2+    halfEdgeSetVertex he' =<< halfEdgeVertex e1++    halfEdgeSetNext he e1+    halfEdgeSetPrev he e2_prev++    halfEdgeSetNext he' e2+    halfEdgeSetPrev he' =<< halfEdgePrev e1++    halfEdgeSetPrev e1 he+    halfEdgeSetNext e2_prev he++    halfEdgeSetNext e1_prev he'+    halfEdgeSetPrev e2 he'++    face <- faceNew pg+    faceSetHalfEdge face he'+    halfEdgeWithLoop he' (`halfEdgeSetFace` face)++    pure $ Edge (halfEdgeToId he `div` 2) pg++-- pgInsertVertex :: HalfEdge s -> ST s (Vertex s)++-- pgRemoveEdge :: Edge s -> ST s ()+-- pgRemoveEdges :: [Edge s] -> ST s ()+-- pgRemoveVertex :: Vertex s -> ST s ()+-- pgRemoveBorder :: Edge s -> ST s ()++-------------------------------------------------------------------------------+-- Use cases++-- Use cases:+--   Triangulate polygon.+--     Create PlanarGraph from polygon. Holes have unique faces.+--     Update with [LineSegment 2 Vertex r]+--     Update Face ids at the end.+--   Cut planar graph in two.+--   Re-triangulate part of graph.+--   Mesh smoothing.+--     1. Keep vertex positions separate. Can update without changing the graph.+--     2. Swap edges. HalfEdge+Twin. Find next of each. Delete original half-edges.+--        Then insert half-edges to next.
+ src/Data/PlanarGraph/Persistent.hs view
@@ -0,0 +1,71 @@+module Data.PlanarGraph.Persistent where++import Data.HashMap.Strict+import Control.Monad.State++type HalfEdge = Int+type Vertex = Int+type Face = Int++-- PlanarGraphs have vertices, edges, and faces.+-- Invariant: The half-edge of a boundary vertex is interior, twin is exterior.+data PlanarGraph = PlanarGraph+  { pgNextHalfEdgeId     :: HalfEdge+  , pgNextVertexId       :: Vertex+  , pgNextFaceId         :: Face+  , pgNext               :: HashMap HalfEdge HalfEdge+  , pgVertex             :: HashMap HalfEdge Vertex+  , pgFace               :: HashMap HalfEdge Face+  , pgHalfEdgeFromVertex :: HashMap Vertex HalfEdge+  , pgHalfEdgeFromFace   :: HashMap Face HalfEdge+  }++-- data PlaneGraph r = PlaneGraph PlanarGraph (HashMap Vertex (Point 2 r))++new :: Int -> PlanarGraph+new = undefined++-- O(log n)+-- vertexHalfEdge :: Vertex -> PlanarGraph -> HalfEdge+-- O(k log n)+-- vertexOutgoingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+-- O(k log n)+-- vertexIncomingHalfEdges :: Vertex -> PlanarGraph -> [HalfEdge]+-- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex]+-- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face]++halfEdgeNext       :: HalfEdge -> PlanarGraph -> HalfEdge+halfEdgeNext = undefined++halfEdgeNextM       :: MonadState PlanarGraph m => HalfEdge -> m HalfEdge+halfEdgeNextM = gets . halfEdgeNext++-- halfEdgeNext       :: HalfEdge -> PlanarGraph -> HalfEdge+-- halfEdgeVertex     :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeTwin       :: HalfEdge -> PlanarGraph -> HalfEdge+-- halfEdgeTailVertex :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeTipVertex  :: HalfEdge -> PlanarGraph -> Vertex+-- halfEdgeFace       :: HalfEdge -> PlanarGraph -> Face+-- halfEdgeIsInterior++-- faceHalfEdge :: Face -> PlanarGraph -> HalfEdge+-- faceIsInterior+-- faceIsBoundary+-- faceAdjacentVertices :: +-- faceAdjaventFaces :: Face -> PlanarGraph -> [Face]++-- connectVertices :: HalfEdge -> HalfEdge -> PlanarGraph -> PlanarGraph+-- splitHalfEdge :: HalfEdge -> PlanarGraph -> (PlanarGraph, Vertex)++-- Use cases:+--   Triangulate polygon.+--     Create PlanarGraph from polygon. Holes have unique faces.+--     Update with [LineSegment 2 Vertex r]+--     Update Face ids at the end.+--   Cut planar graph in two.+--   Re-triangulate part of graph.+--   Mesh smoothing.+--     1. Keep vertex positions separate. Can update without changing the graph.+--     2. Swap edges. HalfEdge+Twin. Find next of each. Delete original half-edges.+--        Then insert half-edges to next.+
src/Data/Range.hs view
@@ -14,23 +14,25 @@ module Data.Range( EndPoint(..)                  , isOpen, isClosed                  , unEndPoint-                 , Range(..)+                 , Range(.., OpenRange, ClosedRange, Range')                  , prettyShow                  , lower, upper-                 , pattern OpenRange, pattern ClosedRange, pattern Range'                  , inRange, width, clipLower, clipUpper, midPoint, clampTo-                 , isValid, covers+                 , isValidRange, covers                   , shiftLeft, shiftRight                  ) where +import Control.Monad((<=<)) import Control.DeepSeq import Control.Lens+import Control.Applicative import Data.Intersection import Data.Vinyl.CoRec import GHC.Generics (Generic) import Test.QuickCheck-import Text.Printf (printf)+import Data.Functor.Classes+import Text.Read  -------------------------------------------------------------------------------- -- * Representing Endpoints of a Range@@ -38,8 +40,26 @@ -- | Endpoints of a range may either be open or closed. data EndPoint a = Open   !a                 | Closed !a-                deriving (Show,Read,Eq,Functor,Foldable,Traversable,Generic,NFData)+                deriving (Eq,Functor,Foldable,Traversable,Generic,NFData) +instance (Show a) => Show (EndPoint a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 EndPoint where+  liftShowsPrec sp _sl d (Open a)   = showsUnaryWith sp "Open" d a+  liftShowsPrec sp _sl d (Closed a) = showsUnaryWith sp "Closed" d a++instance (Read a) => Read (EndPoint a) where+  readPrec     = liftReadPrec readPrec readListPrec+  readListPrec = readListPrecDefault++instance Read1 EndPoint where+  liftReadPrec rp _rl = readData $+      readUnaryWith rp "Open" Open <|>+      readUnaryWith rp "Closed" Closed+  liftReadListPrec = liftReadListPrecDefault++ instance Ord a => Ord (EndPoint a) where   -- | order on the actual value, and Open before Closed   a `compare` b = f a `compare` f b@@ -56,6 +76,14 @@ _unEndPoint (Open a)   = a _unEndPoint (Closed a) = a +-- | Access lens for EndPoint value regardless of whether it is open or closed.+--+-- >>> Open 5 ^. unEndPoint+-- 5+-- >>> Closed 10 ^. unEndPoint+-- 10+-- >>> Open 4 & unEndPoint .~ 0+-- Open 0 unEndPoint :: Lens (EndPoint a) (EndPoint b) a b unEndPoint = lens _unEndPoint f   where@@ -63,10 +91,12 @@     f (Closed _) a = Closed a {-# INLINE unEndPoint #-} +-- | True iff EndPoint is open. isOpen          :: EndPoint a -> Bool-isOpen (Open _) = True-isOpen _        = False+isOpen Open{} = True+isOpen _      = False +-- | True iff EndPoint is closed. isClosed :: EndPoint a -> Bool isClosed = not . isOpen @@ -79,12 +109,35 @@                      , _upper :: !(EndPoint a)                      }                deriving (Eq,Functor,Foldable,Traversable,Generic,NFData)-makeLenses ''Range -instance Show a => Show (Range a) where-  show (Range l u) = printf "Range (%s) (%s)" (show l) (show u)+-- | Lens access for the lower part of a range.+lower :: Lens' (Range a) (EndPoint a)+lower = lens _lower (\r l -> r{_lower=l}) +-- | Lens access for the upper part of a range.+upper :: Lens' (Range a) (EndPoint a)+upper = lens _upper (\r u -> r{_upper=u}) +-- instance Show a => Show (Range a) where+--   show (Range l u) = printf "Range (%s) (%s)" (show l) (show u)++instance (Show a) => Show (Range a) where+  showsPrec = liftShowsPrec showsPrec showList++instance Show1 Range where+  liftShowsPrec sp sl d (Range l u) =+      showsBinaryWith (liftShowsPrec sp sl) (liftShowsPrec sp sl) "Range" d l u++instance (Read a) => Read (Range a) where+  readPrec     = liftReadPrec readPrec readListPrec+  readListPrec = readListPrecDefault++instance Read1 Range where+  liftReadPrec rp rl = readData $+      readBinaryWith (liftReadPrec rp rl) (liftReadPrec rp rl) "Range" Range+  liftReadListPrec = liftReadListPrecDefault++ pattern OpenRange       :: a -> a -> Range a pattern OpenRange   l u = Range (Open l)   (Open u) @@ -156,14 +209,16 @@  type instance IntersectionOf (Range a) (Range a) = [ NoIntersection, Range a] -instance Ord a => (Range a) `IsIntersectableWith` (Range a) where+instance Ord a => Range a `HasIntersectionWith` Range a+instance Ord a => Range a `IsIntersectableWith` Range a where    nonEmptyIntersection = defaultNonEmptyIntersection    -- The intersection is empty, if after clipping, the order of the end points is inverted   -- or if the endpoints are the same, but both are open.-  (Range l u) `intersect` s = let i = clipLower' l . clipUpper' u $ s-                              in if isValid i then coRec i else coRec NoIntersection+  (Range l u) `intersect` s = case (clipLower l <=< clipUpper u $ s) of+                                Nothing -> coRec NoIntersection+                                Just i  -> coRec i  -- | Get the width of the interval --@@ -174,6 +229,7 @@ width   :: Num r => Range r -> r width i = i^.upper.unEndPoint - i^.lower.unEndPoint +-- | Compute the halfway point between the start and end of a range. midPoint   :: Fractional r => Range r -> r midPoint r = let w = width r in r^.lower.unEndPoint + (w / 2) @@ -204,63 +260,45 @@ -- | Clip the interval from below. I.e. intersect with the interval {l,infty), -- where { is either open, (, orr closed, [. clipLower     :: Ord a => EndPoint a -> Range a -> Maybe (Range a)-clipLower l r = let r' = clipLower' l r in if isValid r' then Just r' else Nothing+clipLower p rr@(Range l r) = case (p^.unEndPoint) `compare` (r^.unEndPoint) of+                               GT                        -> Nothing+                               EQ | isOpen r || isOpen p -> Nothing+                               _                         -> Just $+                                 case (p^.unEndPoint) `compare` (l^.unEndPoint) of+                                   LT -> rr+                                   EQ -> if isOpen p then Range p r else rr+                                   GT -> Range p r  -- | Clip the interval from above. I.e. intersect with (-\infty, u}, where } is -- either open, ), or closed, ], clipUpper     :: Ord a => EndPoint a -> Range a -> Maybe (Range a)-clipUpper u r = let r' = clipUpper' u r in if isValid r' then Just r' else Nothing+clipUpper p (Range l r) = case (p^.unEndPoint) `compare` (l^.unEndPoint) of+                            LT                        -> Nothing+                            EQ | isOpen l || isOpen p -> Nothing+                            _                         -> Just $ Range l (p `min` r) + -- | Wether or not the first range completely covers the second one covers       :: forall a. Ord a => Range a -> Range a -> Bool-x `covers` y = maybe False (== y) . asA @(Range a) $ x `intersect` y-+x `covers` y = (== Just y) . asA @(Range a) $ x `intersect` y  -- | Check if the range is valid and nonEmpty, i.e. if the lower endpoint is -- indeed smaller than the right endpoint. Note that we treat empty open-ranges -- as invalid as well.-isValid             :: Ord a => Range a -> Bool-isValid (Range l u) = case (_unEndPoint l) `compare` (_unEndPoint u) of-                          LT                            -> True-                          EQ | isClosed l || isClosed u -> True-                          _                             -> False---- operation is unsafe, as it may produce an invalid range (where l > u)-clipLower'                  :: Ord a => EndPoint a -> Range a -> Range a-clipLower' l' r@(Range l u) = case l' `cmpLower` l of-                                GT -> Range l' u-                                _  -> r--- operation is unsafe, as it may produce an invalid range (where l > u)-clipUpper'                  :: Ord a => EndPoint a -> Range a -> Range a-clipUpper' u' r@(Range l u) = case u' `cmpUpper` u of-                                LT -> Range l u'-                                _  -> r---- | Compare end points, Closed < Open-cmpLower     :: Ord a => EndPoint a -> EndPoint a -> Ordering-cmpLower a b = case (_unEndPoint a) `compare` (_unEndPoint b) of-                 LT -> LT-                 GT -> GT-                 EQ -> case (a,b) of-                         (Open _,   Open _)   -> EQ  -- if both are same type, report EQ-                         (Closed _, Closed _) -> EQ-                         (Open _,  _)         -> GT  -- otherwise, choose the Closed one-                         (Closed _,_)         -> LT  -- is the *smallest*----- | Compare the end points, Open < Closed-cmpUpper     :: Ord a => EndPoint a -> EndPoint a -> Ordering-cmpUpper a b = case (_unEndPoint a) `compare` (_unEndPoint b) of-                 LT -> LT-                 GT -> GT-                 EQ -> case (a,b) of-                         (Open _,   Open _)   -> EQ  -- if both are same type, report EQ-                         (Closed _, Closed _) -> EQ-                         (Open _,  _)         -> LT  -- otherwise, choose the Closed one-                         (Closed _,_)         -> GT  -- is the *largest*---+--+-- >>> isValidRange $ Range (Open 4) (Closed 4)+-- False+-- >>> isValidRange $ Range (Open 5) (Closed 4)+-- False+-- >>> isValidRange $ Range (Open 4) (Closed 5)+-- True+-- >>> isValidRange $ Range (Closed 5) (Closed 40)+-- True+isValidRange             :: Ord a => Range a -> Bool+isValidRange (Range l u) = case _unEndPoint l `compare` _unEndPoint u of+                             LT                            -> True+                             EQ | isClosed l && isClosed u -> True+                             _                             -> False  -------------------------------------------------------------------------------- 
+ src/Data/RealNumber/Rational.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE DeriveDataTypeable #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.RealNumber.Rational+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Data.RealNumber.Rational(RealNumber(..)++                               -- * Converting to and from RealNumber's+                               , AsFixed(..), asFixed+                               , toFixed, fromFixed+                               , Nat+                               ) where++import Data.Aeson+import Data.Data+import Data.Fixed+import Data.Hashable+import Data.List       (dropWhileEnd)+import GHC.Generics    (Generic (..))+import GHC.TypeLits+import Test.QuickCheck (Arbitrary (..))+import Control.Monad.Random+import Data.Ratio+import           Control.DeepSeq++--------------------------------------------------------------------------------++-- | Real Numbers represented using Rational numbers. The number type+-- itself is exact in the sense that we can represent any rational+-- number.+--+-- The parameter, a natural number, represents the precision (in+-- number of decimals behind the period) with which we display the+-- numbers when printing them (using Show).+--+-- If the number cannot be displayed exactly a '~' is printed after+-- the number.+newtype RealNumber (p :: Nat) = RealNumber Rational+  deriving (Eq,Ord,Data,Num,Fractional,Real,RealFrac,Generic,Hashable,ToJSON,FromJSON,NFData)++data NatPrec (p :: Nat) = NatPrec++instance KnownNat p => HasResolution (NatPrec p) where+  resolution _ = 10 ^ (natVal (NatPrec @p))+++instance KnownNat p => Show (RealNumber p) where+  showsPrec d r = showParen (d > app_prec && r < 0) $+    case asFixed r of+      Exact p -> showString (dropWhileEnd (== '.') . dropWhileEnd (== '0') . show $ p)+      Lossy p -> shows p . showChar '~'+    where+      app_prec = 10++instance KnownNat p => Read (RealNumber p) where+  readsPrec i = map wrap . readsPrec @(Fixed (NatPrec p)) i+    where+      wrap (RealNumber . realToFrac -> x,s') = case s' of+                                                 '~':s'' -> (x,s'')+                                                 _       -> (x,s')++instance KnownNat p => Arbitrary (RealNumber p) where+  arbitrary = fromFixed <$> arbitrary+++instance Random (RealNumber p) where+  -- Generate a random number between a and b with 'maxBound `div` 2 :: Int' discrete increments.+  randomR (a,b) = runRand $ do+    v <- getRandom+    pure $ (b-a)*abs v + a+  -- Generate a random number between -1 and +1 with 'maxBound::Int' discrete increments.+  random = runRand $ do+    v <- getRandom+    let fromInt :: Int -> Integer; fromInt = fromIntegral+    pure $ RealNumber $ fromInt v % fromInt maxBound++--------------------------------------------------------------------------------++++-- | Fixed-precision representation of a 'RealNumber'. If there's insufficient+--   precision to accurately represent the 'RealNumber' then the 'Lossy' constructor+--   will be used.+data AsFixed p = Exact !(Fixed p) | Lossy !(Fixed p) deriving (Show,Eq)++-- | Cast 'RealNumber' to a fixed-precision number. Data is silently lost if there's+--   insufficient precision.+toFixed :: KnownNat p => RealNumber p -> Fixed (NatPrec p)+toFixed = realToFrac++-- | Cast a fixed-precision number to a 'RealNumber'.+fromFixed :: KnownNat p => Fixed (NatPrec p) -> RealNumber p+fromFixed = realToFrac++-- | Cast 'RealNumber' to a fixed-precision number. Data-loss caused by insufficient+--   precision will be marked by the 'Lossy' constructor.+asFixed   :: KnownNat p => RealNumber p -> AsFixed (NatPrec p)+asFixed r = let p = toFixed r in if r == fromFixed p then Exact p else Lossy p
src/Data/Sequence/Util.hs view
@@ -1,47 +1,18 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Sequence.Util+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Data.Sequence.Util where -import Data.Sequence(Seq, ViewL(..),ViewR(..))+import           Algorithms.BinarySearch import qualified Data.Sequence as S-import qualified Data.Vector.Generic as V+import           Data.Sequence (Seq)  -------------------------------------------------------------------------------- --- | Given a monotonic predicate, Get the index h such that everything strictly--- smaller than h has: p i = False, and all i >= h, we have p h = True------ returns Nothing if no element satisfies p------ running time: \(O(\log^2 n + T*\log n)\), where \(T\) is the time to execute the--- predicate.-binarySearchSeq     :: (a -> Bool) -> Seq a -> Maybe Int-binarySearchSeq p s = case S.viewr s of-                       EmptyR                 -> Nothing-                       (_ :> x)   | p x       -> Just $ case S.viewl s of-                         (y :< _) | p y          -> 0-                         _                       -> binarySearch p' 0 u-                                  | otherwise -> Nothing-  where-    p' = p . S.index s-    u  = S.length s - 1---- | Given a monotonic predicate, get the index h such that everything strictly--- smaller than h has: p i = False, and all i >= h, we have p h = True------ returns Nothing if no element satisfies p------ running time: \(O(T*\log n)\), where \(T\) is the time to execute the--- predicate.-binarySearchVec                             :: V.Vector v a-                                            => (a -> Bool) -> v a -> Maybe Int-binarySearchVec p' v | V.null v   = Nothing-                     | not $ p n' = Nothing-                     | otherwise  = Just $ if p 0 then 0-                                                  else binarySearch p 0 n'-  where-    n' = V.length v - 1-    p = p' . (v V.!)-- -- | Partition the seq s given a monotone predicate p into (xs,ys) such that -- -- all elements in xs do *not* satisfy the predicate p@@ -52,25 +23,6 @@ -- running time: \(O(\log^2 n + T*\log n)\), where \(T\) is the time to execute the -- predicate. splitMonotone     :: (a -> Bool) -> Seq a -> (Seq a, Seq a)-splitMonotone p s = case binarySearchSeq p s of+splitMonotone p s = case binarySearchIdxIn p s of                       Nothing -> (s,S.empty)                       Just i  -> S.splitAt i s----- | Given a monotonic predicate p, a lower bound l, and an upper bound u, with:---  p l = False---  p u = True---  l < u.------ Get the index h such that everything strictly smaller than h has: p i =--- False, and all i >= h, we have p h = True------ running time: \(O(\log(u - l))\)-{-# SPECIALIZE binarySearch :: (Int -> Bool) -> Int -> Int -> Int #-}-{-# SPECIALIZE binarySearch :: (Word -> Bool) -> Word -> Word -> Word #-}-binarySearch       :: Integral a => (a -> Bool) -> a -> a -> a-binarySearch p l u = let d = u - l-                         m = l + (d `div` 2)-                     in if d == 1 then u else-                          if p m then binarySearch p l m-                                 else binarySearch p m u
src/Data/Set/Util.hs view
@@ -1,16 +1,23 @@+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Set.Util+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+-------------------------------------------------------------------------------- module Data.Set.Util where  import           Data.DynamicOrd-import qualified Data.Set as Set import           Data.Set (Set)+import qualified Data.Set as Set import qualified Data.Set.Internal as Internal  --- import Data.Ord(comparing)+import           Data.Ord (comparing) --- data S = S String deriving Show--- cmpS :: S -> S -> Ordering--- cmpS = comparing (\(S s) -> length s)+data S = S String deriving Show+cmpS :: S -> S -> Ordering+cmpS = comparing (\(S s) -> length s)   -- $setup@@ -32,6 +39,18 @@                     g c y  = y `compare` x == c                 in (l,m,r) +-- | Given a monotonic function f that orders @a@, split the sequence @s@+-- into three parts. I.e. the result (lt,eq,gt) is such that+-- * all (\x -> f x == LT) . fmap f $ lt+-- * all (\x -> f x == EQ) . fmap f $ eq+-- * all (\x -> f x == GT) . fmap f $ gt+--+-- running time: \(O(\log n)\)+splitBy       :: (a -> Ordering) -> Set a -> (Set a, Set a, Set a)+splitBy f s = let (l,s') = Set.spanAntitone ((==) LT . f) s+                  (m,r)  = Set.spanAntitone ((==) EQ . f) s'+              in (l,m,r)+ -- | Constructs a Set using the given Order. -- -- Note that this is dangerous as the resulting set may not abide the@@ -78,3 +97,44 @@ -- running time: \(O(\log n)\) deleteAllBy         :: (a -> a -> Ordering) -> a -> Set a -> Set a deleteAllBy cmp x s = withOrd cmp $ liftOrd1 (Set.delete $ O x) s++-- | Run a query, eg. lookupGE, on the set with the given ordering.+--+-- Note: The 'Algorithms.BinarySearch.binarySearchIn' function may be+-- a useful alternative to 'queryBy'+--+-- >>> queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "bbb")+-- >>> queryBy cmpS Set.lookupLE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "a")+-- >>> queryBy cmpS Set.lookupGE (S "333") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- Just (S "bbb")+queryBy           :: (a -> a -> Ordering)+                  -> (forall b. Ord b => b -> Set b -> t b)+                  -> a -> Set a -> t a+queryBy cmp fs q s = withOrd cmp $ liftOrd1 (fs $ O q) s+++++-- queryBy'           :: Ord r+--                    => (a -> r)+--                    -> r+--                   -> (forall b. Ord b => b -> Set b -> t b)+--                   -> a -> Set a -> t a+-- queryBy' g fs q s = queryBy+--   where++++--   withOrd cmp $ liftOrd1 (fs $ O q) s++++  -- withOrd cmp $ liftOrd1 (Set.lookupGE $ O q) s+++++-- test = queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- test = succBy cmpS (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]
− src/Data/SlowSeq.hs
@@ -1,205 +0,0 @@-module Data.SlowSeq where---import           Control.Lens (bimap)--- import qualified Data.FingerTree as FT--- import           Data.FingerTree hiding (null, viewl, viewr)-import           Data.FingerTree(ViewL(..),ViewR(..))-import qualified Data.Foldable as F-import           Data.Maybe-import qualified Data.Sequence as S-import qualified Data.Sequence.Util as SU--------------------------------------------------------------------------------------data Key a = NoKey | Key { getKey :: a } deriving (Show,Eq,Ord)--instance Semigroup (Key a) where-  k <> NoKey = k-  _ <> k     = k--instance Monoid (Key a) where-  mempty = NoKey-  k `mappend` k' = k <> k'--liftCmp                     :: (a -> a -> Ordering) -> Key a -> Key a -> Ordering-liftCmp _   NoKey   NoKey   = EQ-liftCmp _   NoKey   (Key _) = LT-liftCmp _   (Key _) NoKey   = GT-liftCmp cmp (Key x) (Key y) = x `cmp` y------ newtype Elem a = Elem { getElem :: a } deriving (Eq,Ord,Traversable,Foldable,Functor)---- instance Show a => Show (Elem a) where---   show (Elem x) = "Elem " <> show x---newtype OrdSeq a = OrdSeq { _asSeq :: S.Seq a }-                   deriving (Show,Eq)--instance Semigroup (OrdSeq a) where-  (OrdSeq s) <> (OrdSeq t) = OrdSeq $ s `mappend` t--instance Monoid (OrdSeq a) where-  mempty = OrdSeq mempty-  mappend = (<>)--instance Foldable OrdSeq where-  foldMap f = foldMap f . _asSeq-  null      = null . _asSeq-  length    = length . _asSeq-  minimum   = fromJust . lookupMin-  maximum   = fromJust . lookupMax---- instance Measured (Key a) (Elem a) where---   measure (Elem x) = Key x---type Compare a = a -> a -> Ordering---- | Insert into a monotone OrdSeq.------ pre: the comparator maintains monotonicity------ \(O(\log^2 n)\)-insertBy                  :: Compare a -> a -> OrdSeq a -> OrdSeq a-insertBy cmp x (OrdSeq s) = OrdSeq $ l `mappend` (x S.<| r)-  where-    (l,r) = split (\v -> cmp v x `elem` [EQ, GT]) s--------- | Insert into a sorted OrdSeq------ \(O(\log^2 n)\)-insert :: Ord a => a -> OrdSeq a -> OrdSeq a-insert = insertBy compare--deleteAllBy         :: Compare a -> a -> OrdSeq a -> OrdSeq a-deleteAllBy cmp x s = l <> r-  where-    (l,_,r) = splitBy cmp x s--    -- (l,m) = split (\v -> liftCmp cmp v (Key x) `elem` [EQ,GT]) s-    -- (_,r) = split (\v -> liftCmp cmp v (Key x) == GT) m----- | \(O(\log^2 n)\)-splitBy                  :: Compare a -> a -> OrdSeq a -> (OrdSeq a, OrdSeq a, OrdSeq a)-splitBy cmp x (OrdSeq s) = (OrdSeq l, OrdSeq m', OrdSeq r)-  where-    (l, m) = split (\v -> cmp v x `elem` [EQ,GT]) s-    (m',r) = split (\v -> cmp v x == GT) m----- | Given a monotonic function f that maps a to b, split the sequence s--- depending on the b values. I.e. the result (l,m,r) is such that--- * all (< x) . fmap f $ l--- * all (== x) . fmap f $ m--- * all (> x) . fmap f $ r------ >>> splitOn id 3 $ fromAscList' [1..5]--- (OrdSeq {_asSeq = fromList [Elem 1,Elem 2]},OrdSeq {_asSeq = fromList [Elem 3]},OrdSeq {_asSeq = fromList [Elem 4,Elem 5]})--- >>> splitOn fst 2 $ fromAscList' [(0,"-"),(1,"A"),(2,"B"),(2,"C"),(3,"D"),(4,"E")]--- (OrdSeq {_asSeq = fromList [Elem (0,"-"),Elem (1,"A")]},OrdSeq {_asSeq = fromList [Elem (2,"B"),Elem (2,"C")]},OrdSeq {_asSeq = fromList [Elem (3,"D"),Elem (4,"E")]})------ \(O(\log^2 n)\)-splitOn :: Ord b => (a -> b) -> b -> OrdSeq a -> (OrdSeq a, OrdSeq a, OrdSeq a)-splitOn f x (OrdSeq s) = (OrdSeq l, OrdSeq m', OrdSeq r)-  where-    (l, m) = split (\v -> compare (f v) x `elem` [EQ,GT]) s-    (m',r) = split (\v -> compare (f v) x ==     GT)      m---- | Given a monotonic predicate p, splits the sequence s into two sequences---  (as,bs) such that all (not p) as and all p bs------ \(O(\log^2 n)\)-splitMonotonic  :: (a -> Bool) -> OrdSeq a -> (OrdSeq a, OrdSeq a)-splitMonotonic p = bimap OrdSeq OrdSeq . split p . _asSeq----- monotonic split for Sequences------ \(O(\log^2 n)\)-split :: (a -> Bool) -> S.Seq a -> (S.Seq a, S.Seq a)-split = SU.splitMonotone---- Deletes all elements from the OrdDeq------ \(O(\log^2 n)\)-deleteAll :: Ord a => a -> OrdSeq a -> OrdSeq a-deleteAll = deleteAllBy compare----- | inserts all eleements in order--- \(O(n\log n)\)-fromListBy     :: Compare a -> [a] -> OrdSeq a-fromListBy cmp = foldr (insertBy cmp) mempty---- | inserts all eleements in order--- \(O(n\log n)\)-fromListByOrd :: Ord a => [a] -> OrdSeq a-fromListByOrd = fromListBy compare---- | O(n)-fromAscList' :: [a] -> OrdSeq a-fromAscList' = OrdSeq . S.fromList----- | \(O(\log^2 n)\)-lookupBy                  :: Compare a -> a -> OrdSeq a -> Maybe a-lookupBy cmp x s = let (_,m,_) = splitBy cmp x s in listToMaybe . F.toList $ m--memberBy        :: Compare a -> a -> OrdSeq a -> Bool-memberBy cmp x = isJust . lookupBy cmp x----- | Fmap, assumes the order does not change--- \(O(n)\)-mapMonotonic   :: (a -> b) -> OrdSeq a -> OrdSeq b-mapMonotonic f = fromAscList' . map f . F.toList----- | Gets the first element from the sequence--- \(O(1)\)-viewl :: OrdSeq a -> ViewL OrdSeq a-viewl = f . S.viewl . _asSeq-  where-    f S.EmptyL         = EmptyL-    f (x S.:< s)  = x :< OrdSeq s---- Last element--- \(O(1)\)-viewr :: OrdSeq a -> ViewR OrdSeq a-viewr = f . S.viewr . _asSeq-  where-    f S.EmptyR    = EmptyR-    f (s S.:> x)  = OrdSeq s :> x----- \(O(1)\)-minView   :: OrdSeq a -> Maybe (a, OrdSeq a)-minView s = case viewl s of-              EmptyL   -> Nothing-              (x :< t) -> Just (x,t)---- \(O(1)\)-lookupMin :: OrdSeq a -> Maybe a-lookupMin = fmap fst . minView---- \(O(1)\)-maxView   :: OrdSeq a -> Maybe (a, OrdSeq a)-maxView s = case viewr s of-              EmptyR   -> Nothing-              (t :> x) -> Just (x,t)---- \(O(1)\)-lookupMax :: OrdSeq a -> Maybe a-lookupMax = fmap fst . maxView
src/Data/Tree/Util.hs view
@@ -1,10 +1,16 @@+-- | Tree-related utilities. module Data.Tree.Util where -import Data.Maybe(listToMaybe,maybeToList)-import Control.Lens-import Control.Monad((>=>))-import Data.Tree+import           Data.Bifoldable+import           Data.Bifunctor+import           Data.Bitraversable+import           Control.Lens+import           Control.Monad ((>=>)) import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import           Data.List.NonEmpty (NonEmpty(..))+import           Data.Maybe (listToMaybe,maybeToList)+import           Data.Tree  -------------------------------------------------------------------------------- @@ -16,7 +22,31 @@ --                     ] -- :} + --------------------------------------------------------------------------------++-- | Nodes in a tree are typically either an internal node or a leaf node+data TreeNode v a = InternalNode v | LeafNode a deriving (Show,Eq)++instance Bifunctor TreeNode where+  bimap = bimapDefault+instance Bifoldable TreeNode where+  bifoldMap = bifoldMapDefault+instance Bitraversable TreeNode where+  bitraverse f g = \case+    InternalNode v -> InternalNode <$> f v+    LeafNode l     -> LeafNode     <$> g l++-- | A TreeNode is isomorphic to Either+_TreeNodeEither :: Iso' (TreeNode v p) (Either v p)+_TreeNodeEither = iso tne etn+  where+    tne = \case+      InternalNode v -> Left v+      LeafNode l     -> Right l+    etn = either InternalNode LeafNode++-------------------------------------------------------------------------------- -- * Zipper on rose trees  -- | Zipper for rose trees@@ -50,16 +80,16 @@ -- Just (Zipper {focus = Node {rootLabel = 2, subForest = []}, ancestors = [([Node {rootLabel = 1, subForest = []}],0,[Node {rootLabel = 3, subForest = [Node {rootLabel = 4, subForest = []}]}])]}) nextSibling               :: Zipper a -> Maybe (Zipper a) nextSibling (Zipper t as) = case as of-                              []                  -> Nothing -- no parent-                              ((_,_,[]):_)        -> Nothing -- no next sibling-                              ((ls,p,(r:rs)):as') -> Just $ Zipper r ((t:ls,p,rs):as')+                              []                -> Nothing -- no parent+                              ((_,_,[]):_)      -> Nothing -- no next sibling+                              ((ls,p,r:rs):as') -> Just $ Zipper r ((t:ls,p,rs):as')  -- | Move the focus to the next sibling of this node prevSibling               :: Zipper a -> Maybe (Zipper a) prevSibling (Zipper t as) = case as of-                              []                  -> Nothing -- no parent-                              (([],_,_):_)        -> Nothing -- no prev sibling-                              (((l:ls),p,rs):as') -> Just $ Zipper l ((ls,p,t:rs):as')+                              []                -> Nothing -- no parent+                              (([],_,_):_)      -> Nothing -- no prev sibling+                              ((l:ls,p,rs):as') -> Just $ Zipper l ((ls,p,t:rs):as')  -- | Given a zipper that focussses on some subtree t, construct a list with -- zippers that focus on each child.@@ -103,15 +133,15 @@ -- running time: \(O(nT(n))\) where \(n\) is the size of the tree, and \(T(m)\) is -- the time to evaluate a predicate on a subtree of size \(m\). findEvert'   :: (Tree a -> Bool) -> Tree a -> Maybe (Tree a)-findEvert' p = fmap unZipperLocal . listToMaybe . filter (p . focus) . allTrees . root+findEvert' p = fmap unZipperLocal . List.find (p . focus) . allTrees . root  -- | Function to extract a path between a start node and an end node (if such a --path exists). If there are multiple paths, no guarantees are given about --which one is returned. -- -- running time: \(O(n(T_p+T_s)\), where \(n\) is the size of the tree, and--- \(T_p\) and \(T_s\) are the times it takes to evaluate the 'isStartingNode'--- and 'isEndingNode' predicates.+-- \(T_p\) and \(T_s\) are the times it takes to evaluate the @isStartingNode@+-- and @isEndingNode@ predicates. -- -- -- >>> findPath (== 1) (==4) myTree@@ -150,5 +180,29 @@ findNodes   :: (Tree a -> Bool) -> Tree a -> [[a]] findNodes p = go   where-    go t = let mh = if p t then [[]] else []+    go t = let mh = [ [] | p t ] -- [[]] iff 'p t'            in map (rootLabel t:) $ mh <> concatMap go (children t)+++-- | BFS Traversal of the rose tree that decomposes it into levels.+--+-- running time: \(O(n)\)+levels :: Tree a -> NonEmpty (NonEmpty a)+levels = go1 . (:| [])+  where+    go0   :: [Tree a] -> [NonEmpty a]+    go0 q = case NonEmpty.nonEmpty q of+              Nothing -> []+              Just q1 -> NonEmpty.toList $ go1 q1+    {-# INLINE go0 #-}++    -- all work essentially happens here: given a bunch of trees whose+    -- root elements all have the same level, extract the values+    -- stored at these root nodes, collect all children in a big list,+    -- and explore those recursively.+    go1    :: NonEmpty (Tree a) -> NonEmpty (NonEmpty a)+    go1 qs = fmap root' qs :| go0 (concatMap children' qs)+    {-# INLINE go1 #-}++    root'     (Node x _)   = x+    children' (Node _ chs) = chs
src/Data/UnBounded.hs view
@@ -1,33 +1,47 @@-{-# LANGUAGE TemplateHaskell   #-}-module Data.UnBounded( Top, topToMaybe-                     , pattern ValT, pattern Top-                     , _ValT, _Top+{-# LANGUAGE LambdaCase      #-}+{-# LANGUAGE TemplateHaskell #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.UnBounded+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--+-- Add an unbounded/infintity element to a data type. Essentially,+-- t'Bottom' adds \(-\infty\) (and is pretty much identical to Maybe),+-- whereas t'Top' adds \(\infty\). The 'UnBounded' type adds both.+--+--------------------------------------------------------------------------------+module Data.UnBounded( Top( ValT, Top), topToMaybe+                     , _ValT, _Top, _TopMaybe -                     , Bottom, bottomToMaybe-                     , pattern Bottom, pattern ValB-                     , _ValB, _Bottom+                     , Bottom(Bottom, ValB), bottomToMaybe+                     , _ValB, _Bottom, _BottomMaybe                       , UnBounded(..)-                     , unUnBounded-                     , _MinInfinity, _Val, _MaxInfinity+                     , _Val                      , unBoundedToMaybe                      ) where  import           Control.Lens-import qualified Data.Foldable as F-import qualified Data.Traversable as T+import qualified Data.Foldable        as F import           Data.Functor.Classes+import qualified Data.Traversable     as T  -------------------------------------------------------------------------------- -- * Top and Bottom --- | `Top a` represents the type a, together with a 'Top' element, i.e. an element+-- | @Top a@ represents the type a, together with a v'Top' element, i.e. an element -- that is greater than any other element. We can think of `Top a` being defined as: -- -- >>> data Top a = ValT a | Top-newtype Top a = GTop { topToMaybe :: Maybe a }+newtype Top a = GTop (Maybe a)                 deriving (Eq,Functor,F.Foldable,T.Traversable,Applicative,Monad,Eq1) +-- | @Top a@ values are isomorphing to @Maybe a@ values.+topToMaybe :: Top a -> Maybe a+topToMaybe (GTop mb) = mb+ pattern ValT  :: a -> Top a pattern ValT x = GTop (Just x) @@ -50,22 +64,49 @@   show Top       = "Top"   show ~(ValT x) = "ValT " ++ show x +-- | 'ValT' prism. Can be used to access the non-bottom element if it exists:+--+-- >>> ValT True & _ValT %~ not+-- ValT False+--+-- >>> Top & _ValT %~ not+-- Top _ValT :: Prism (Top a) (Top b) a b-_ValT = prism ValT (\ta -> case ta of Top -> Left Top ; ValT x -> Right x)+_ValT = prism ValT (\case Top -> Left Top ; ValT x -> Right x) +-- | t'Top' prism. _Top :: Prism' (Top a) ()-_Top = prism' (const Top) (\ta -> case ta of Top -> Just () ; ValT _ -> Nothing)+_Top = prism' (const Top) (\case Top -> Just () ; ValT _ -> Nothing) +-- | Iso between a @Top a@ and a @Maybe a@, interpreting a v'Top' as a+-- 'Nothing' and vice versa. Note that this reverses the ordering of+-- the elements.+--+-- >>> ValT 5 ^. _TopMaybe+-- Just 5+-- >>> Just 5 ^.re _TopMaybe+-- ValT 5+-- >>> Top ^. _TopMaybe+-- Nothing+-- >>> Nothing ^.re _TopMaybe+-- Top+_TopMaybe :: Iso' (Top a) (Maybe a)+_TopMaybe = iso topToMaybe GTop+ -------------------------------------------------------------------------------- --- | `Bottom a` represents the type a, together with a 'Bottom' element,+-- | @`Bottom a`@ represents the type a, together with a v'Bottom' element, -- i.e. an element that is smaller than any other element. We can think of--- `Bottom a` being defined as:+-- @`Bottom a`@ being defined as: -- -- >>> data Bottom a = Bottom | ValB a-newtype Bottom a = GBottom { bottomToMaybe :: Maybe a }+newtype Bottom a = GBottom (Maybe a)                  deriving (Eq,Ord,Functor,F.Foldable,T.Traversable,Applicative,Monad,Eq1,Ord1) +-- | `Bottom a` values are isomorphing to `Maybe a` values.+bottomToMaybe :: Bottom a -> Maybe a+bottomToMaybe (GBottom mb) = mb+ pattern Bottom :: Bottom a pattern Bottom = GBottom Nothing @@ -78,12 +119,34 @@   show Bottom    = "Bottom"   show ~(ValB x) = "ValB " ++ show x +-- | 'ValB' prism. Can be used to access the non-bottom element if it exists:+--+-- >>> ValB True & _ValB %~ not+-- ValB False+--+-- >>> Bottom & _ValB %~ not+-- Bottom _ValB :: Prism (Bottom a) (Bottom b) a b-_ValB = prism ValB (\ba -> case ba of Bottom -> Left Bottom ; ValB x -> Right x)+_ValB = prism ValB (\case Bottom -> Left Bottom ; ValB x -> Right x) +-- | t'Bottom' prism. _Bottom :: Prism' (Bottom a) ()-_Bottom = prism' (const Bottom) (\ba -> case ba of Bottom -> Just () ; ValB _ -> Nothing)+_Bottom = prism' (const Bottom) (\case Bottom -> Just () ; ValB _ -> Nothing) +-- | Iso between a 'Bottom a' and a 'Maybe a', interpreting a Bottom as a+-- Nothing and vice versa.+--+-- >>> ValB 5 ^. _BottomMaybe+-- Just 5+-- >>> Just 5 ^.re _BottomMaybe+-- ValB 5+-- >>> Bottom ^. _BottomMaybe+-- Nothing+-- >>> Nothing ^.re _BottomMaybe+-- Bottom+_BottomMaybe :: Iso' (Bottom a) (Maybe a)+_BottomMaybe = iso bottomToMaybe GBottom+ --------------------------------------------------------------------------------  -- | `UnBounded a` represents the type a, together with an element@@ -91,8 +154,26 @@ -- smaller than any other element. data UnBounded a = MinInfinity | Val { _unUnBounded :: a }  | MaxInfinity                  deriving (Eq,Ord,Functor,F.Foldable,T.Traversable)-makeLenses ''UnBounded-makePrisms ''UnBounded++-- | Prism to access unbounded value if it exists.+--+-- >>> Val True ^? _Val+-- Just True+--+-- >>> MinInfinity ^? _Val :: Maybe Bool+-- Nothing+--+-- >>> Val True & _Val %~ not+-- Val False+--+-- >>> MaxInfinity & _Val %~ not+-- MaxInfinity+_Val :: Prism (UnBounded a) (UnBounded b) a b+_Val = prism Val fromUnBounded+  where+    fromUnBounded MinInfinity = Left MinInfinity+    fromUnBounded MaxInfinity = Left MaxInfinity+    fromUnBounded (Val v)     = Right v  instance Show a => Show (UnBounded a) where   show MinInfinity = "MinInfinity"
src/Data/Util.hs view
@@ -10,17 +10,18 @@ -------------------------------------------------------------------------------- module Data.Util where -import Control.DeepSeq-import Control.Lens-import GHC.Generics (Generic)+import           Control.DeepSeq+import           Control.Lens import qualified Data.List as List+import           GHC.Generics (Generic)+import           Linear.V2 (V2(..))+import           Linear.V3 (V3(..))  -------------------------------------------------------------------------------- -- * Strict Triples  -- |  strict triple-data STR a b c = STR { fst' :: !a, snd' :: !b , trd' :: !c}-               deriving (Show,Eq,Ord,Functor,Generic)+data STR a b c = STR !a !b !c deriving (Show,Eq,Ord,Functor,Generic)  instance (Semigroup a, Semigroup b, Semigroup c) => Semigroup (STR a b c) where   (STR a b c) <> (STR d e f) = STR (a <> d) (b <> e) (c <> f)@@ -33,22 +34,29 @@ instance (NFData a, NFData b, NFData c) => NFData (STR a b c)  instance Field1 (STR a b c) (STR d b c) a d where-  _1 = lens fst' (\(STR _ b c) d -> STR d b c)+  _1 = lens (\(STR a _ _) -> a) (\(STR _ b c) d -> STR d b c)  instance Field2 (STR a b c) (STR a d c) b d where-  _2 = lens snd' (\(STR a _ c) d -> STR a d c)+  _2 = lens (\(STR _ b _) -> b) (\(STR a _ c) d -> STR a d c)  instance Field3 (STR a b c) (STR a b d) c d where-  _3 = lens trd' (\(STR a b _) d -> STR a b d)---- | Generate All unique unordered triplets.----uniqueTriplets    :: [a] -> [STR a a a]-uniqueTriplets xs = [ STR x y z | (x:ys) <- nonEmptyTails xs, SP y z <- uniquePairs ys]+  _3 = lens (\(STR _ _ c) -> c) (\(STR a b _) d -> STR a b d) +-------------------------------------------------------------------------------- +--------------------------------------------------------------------------------+-- | Strict Triple with all items the same+type Three = V3 +-- | Pattern synonym for strict triples.+pattern Three :: a -> a -> a -> Three a+pattern Three a b c = V3 a b c+{-# COMPLETE Three #-} +-- | Generate All unique unordered triplets.+--+uniqueTriplets    :: [a] -> [Three a]+uniqueTriplets xs = [ Three x y z | (x:ys) <- nonEmptyTails xs, Two y z <- uniquePairs ys]  -------------------------------------------------------------------------------- -- * Strict Pairs@@ -80,10 +88,11 @@ -- | * Strict pair whose elements are of the same type.  -- | Strict pair with both items the same-type Two a = SP a a+type Two = V2 +-- | Pattern synonym for strict pairs. pattern Two :: a -> a -> Two a-pattern Two a b = SP a b+pattern Two a b = V2 a b {-# COMPLETE Two #-}  -- | Given a list xs, generate all unique (unordered) pairs.@@ -91,14 +100,6 @@ -- uniquePairs    :: [a] -> [Two a] uniquePairs xs = [ Two x y | (x:ys) <- nonEmptyTails xs, y <- ys ]------------------------------------------------------------------------------------- | Strict Triple with all items the same-type Three a = STR a a a--pattern Three :: a -> a -> a -> Three a-pattern Three a b c = STR a b c-{-# COMPLETE Three #-}  -------------------------------------------------------------------------------- 
+ src/Data/Vector/Circular/Util.hs view
@@ -0,0 +1,74 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Data.Vector.Circular.Util+-- Copyright   :  (C) Frank Staals, David Himmelstrup+-- License     :  see the LICENSE file+-- Maintainer  :  David Himmelstrup+--------------------------------------------------------------------------------+module Data.Vector.Circular.Util where++import           Algorithms.StringSearch.KMP (isSubStringOf)+import           Control.Lens+import           Data.Ext+import           Data.Maybe+import           Data.Semigroup.Foldable+import qualified Data.Vector as V+import           Data.Vector.Circular as CV+import qualified Data.Vector.NonEmpty as NV+import           Test.QuickCheck (Arbitrary (..), NonEmptyList (..))+++-- FIXME: Upstream this to the non-empty vector library?+instance Foldable1 NV.NonEmptyVector++-- | Access the ith item in the CircularVector (w.r.t the rotation) as a lens+item   :: Int -> Lens' (CircularVector a) a+item i = lens (`CV.index` i) (\s x -> unsafeFromVector (toVector s V.// [(i,x)]))++-- | All elements, starting with the focus, going to the right+--+-- >>> rightElements $ unsafeFromList [3,4,5,1,2]+-- [3,4,5,1,2]+rightElements :: CircularVector a -> NV.NonEmptyVector a+rightElements = toNonEmptyVector++-- | All elements, starting with the focus, going to the left+--+-- >>> leftElements $ unsafeFromList [3,4,5,1,2]+-- [3,2,1,5,4]+leftElements :: CircularVector a -> NV.NonEmptyVector a+leftElements v = NV.generate1 (length v) (CV.index v . negate)++-- | Finds an element in the CircularVector+--+-- >>> findRotateTo (== 3) $ unsafeFromList [1..5]+-- Just (CircularVector {vector = [1,2,3,4,5], rotation = 2})+-- >>> findRotateTo (== 7) $ unsafeFromList [1..5]+-- Nothing+findRotateTo   :: (a -> Bool) -> CircularVector a -> Maybe (CircularVector a)+findRotateTo p (CircularVector v _rot) = CircularVector v <$> NV.findIndex p v++-- | Test if the circular list is a cyclic shift of the second+-- list.+--+-- Running time: \(O(n+m)\), where \(n\) and \(m\) are the sizes of+-- the lists.+isShiftOf         :: Eq a => CircularVector a -> CircularVector a -> Bool+xs `isShiftOf` ys = let twice zs    = let zs' = leftElements zs in zs' <> zs'+                        once        = leftElements+                        check as bs = isJust $ once as `isSubStringOf` twice bs+                    in length xs == length ys && check xs ys++instance Arbitrary a => Arbitrary (CircularVector a) where+  arbitrary = unsafeFromList <$> (getNonEmpty <$> arbitrary)++-- | label the circular vector with indices, starting from zero at the+-- current focus, going right.+--+-- Running time: \(O(n)\)+withIndicesRight                      :: CircularVector a -> CircularVector (Int :+ a)+withIndicesRight (CircularVector v s) = CircularVector v' s+  where+    n  = length v+    v' = NV.imap (\i x -> ((i-s) `mod` n) :+ x) v
src/Data/Yaml/Util.hs view
@@ -66,6 +66,7 @@                              , content :: a                              } deriving (Show,Read,Generic,Eq,Functor,Foldable,Traversable) +-- | Unpack versioned data type. unversioned :: Versioned a -> a unversioned = content 
test/Algorithms/DivideAndConquerSpec.hs view
@@ -1,10 +1,11 @@ module Algorithms.DivideAndConquerSpec where  import Algorithms.DivideAndConquer- import           Test.Hspec import           Test.QuickCheck import qualified Data.List as List++--------------------------------------------------------------------------------  spec = describe "divide and conquer strategy tests" $ do          it "mergeSort" $ property $
+ test/Algorithms/Graph/BFSSpec.hs view
@@ -0,0 +1,26 @@+module Algorithms.Graph.BFSSpec (spec) where++import           Algorithms.Graph.BFS+import           Data.Tree+import qualified Data.Vector as V+import           Test.Hspec++--------------------------------------------------------------------------------++spec :: Spec+spec = it "BFS test" $+         bfs' 0 testGr `shouldBe` answer++testGr :: V.Vector [Int]+testGr = V.fromList [ [1,3, 6]+                    , [2]+                    , [3, 5]+                    , [2 ]+                    , []+                    , [4, 5]+                    , [7]+                    , [8,4]+                    , [2]+                    ]+answer :: Tree Int+answer = Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = [Node {rootLabel = 5, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 6, subForest = [Node {rootLabel = 7, subForest = [Node {rootLabel = 8, subForest = []},Node {rootLabel = 4, subForest = []}]}]}]}
+ test/Algorithms/Graph/DFSSpec.hs view
@@ -0,0 +1,29 @@+module Algorithms.Graph.DFSSpec (spec) where+++import           Algorithms.Graph.DFS  (dfsSensitive)+import           Control.DeepSeq       (NFData (rnf))+import           Control.Exception     (evaluate)+import qualified Data.Foldable         as F+import           Data.PlanarGraph (VertexId (VertexId), World (Primal))+import qualified Data.Set              as S+import           Data.Tree             (Tree (rootLabel, subForest))+import           Test.Hspec            (Spec, anyErrorCall, describe, it, shouldBe, shouldThrow)++{-+  0+ / \+1   2+-}+tree1 :: Tree (VertexId () Primal)+tree1 = dfsSensitive (\i -> case i of VertexId 0 -> [VertexId 1, VertexId 2]; _ -> error "fail!") (VertexId 0)++spec :: Spec+spec = do+  describe "DFS output sensitivity" $ do+    it "fails when forced" $+      evaluate (rnf tree1) `shouldThrow` anyErrorCall+    it "outputs root label lazily" $+      rootLabel tree1 `shouldBe` VertexId 0+    it "outputs forest lazily" $+      length (subForest tree1) `shouldBe` 2
+ test/Algorithms/LogarithmicMethodSpec.hs view
@@ -0,0 +1,45 @@+module Algorithms.LogarithmicMethodSpec where++import           Algorithms.LogarithmicMethod+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.Maybe (mapMaybe)+import           Data.Semigroup+import           Data.Semigroup.Foldable+import           Data.List.Util+import           Test.Hspec+import           Test.QuickCheck++--------------------------------------------------------------------------------++spec :: Spec+spec = describe "Logarithmic method successor test" $ do+         it "successor test" $ property $+           \q (xs :: [Int]) ->+             successor q (fromList xs)+             `shouldBe`+             minimum1 [ x | x <- xs, x >= q]++         it "merge test" $ property $+           \q (xs :: [Int]) (ys :: [Int]) ->+             successor q ((fromList xs) <> (fromList ys))+             `shouldBe`+             successor q (fromList $ xs <> ys)+++newtype DummySucc a = Dummy (NonEmpty a)+  deriving (Show,Eq,Functor,Foldable,Foldable1,Traversable)++instance Ord a => LogarithmicMethodDS DummySucc a where+  build = Dummy . NonEmpty.sort++successor'              :: Ord a => a -> DummySucc a -> Maybe (Min a)+successor' q (Dummy xs) = case NonEmpty.dropWhile (< q) xs of+                            []    -> Nothing+                            (s:_) -> Just (Min s)++successor   :: Ord a => a -> InsertionOnly DummySucc a -> Maybe a+successor q = fmap getMin . queryWith (successor' q)++fromList :: Ord a => [a] -> InsertionOnly DummySucc a+fromList = foldr insert empty
test/Data/CircularSeqSpec.hs view
@@ -39,6 +39,9 @@       --              let cs  = fromNonEmpty xs       --                  cs' = rotateNR i cs       --              in+    it "read . show = id" $ do+      property $ \(lst :: CSeq Rational) ->+        read (show lst) == lst   
test/Data/EdgeOracleSpec.hs view
@@ -3,7 +3,7 @@ import           Control.Arrow import           Data.Ext import           Data.PlanarGraph.EdgeOracle-import           Data.PlanarGraph.Core+import           Data.PlanarGraph import           Data.Semigroup import qualified Data.Set as S import           Test.Hspec
+ test/Data/IndexedDoublyLinkedListSpec.hs view
@@ -0,0 +1,36 @@+module Data.IndexedDoublyLinkedListSpec where++import           Control.Monad.ST+import           Data.IndexedDoublyLinkedList+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.Vector as V+import           Test.Hspec++--------------------------------------------------------------------------------++spec :: Spec+spec = do+  describe "IndexedDoublyLinkedList tests" $ do+    it "myTest" $+      runT myProg `shouldBe` (4 :| [2,1,0],4 :| [5,8])+    it "myTest'" $+      runT myProg' `shouldBe` ('e' :| "cba",'e' :| "fi")+++runT   :: (forall s. DLListMonad s Char a) -> a+runT c = runDLListMonad (V.fromList "abcdefghi") c++myProg :: DLListMonad s b (NonEmpty Index, NonEmpty Index)+myProg = do writeList (0 :| [2,4,6,8])+            delete 6+            insertBefore 2 1+            insertAfter 4 5+            as <- toListFromR 4+            bs <- toListFrom 4+            pure (as,bs)++myProg' :: DLListMonad s b (NonEmpty b, NonEmpty b)+myProg' = do (as,bs) <- myProg+             as' <- mapM valueAt as+             bs' <- mapM valueAt bs+             pure (as',bs')
test/Data/PlanarGraphSpec.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE ScopedTypeVariables #-} module Data.PlanarGraphSpec where -+import Control.Lens(view,_3) import           Data.Bifunctor import qualified Data.ByteString.Char8 as B import qualified Data.Foldable as F@@ -90,7 +90,7 @@ fromAdjacencyListsOld adjM = planarGraph' . toCycleRep n $ perm   where     n    = sum . fmap length $ perm-    perm = trd' . foldr toOrbit (STR mempty 0 mempty) $ adjM+    perm = view (_3) . foldr toOrbit (STR mempty 0 mempty) $ adjM       -- | Given a vertex with its adjacent vertices (u,vs) (in CCW order) convert this
test/Data/RangeSpec.hs view
@@ -18,6 +18,11 @@     it "closed cap open, disjoint" $ do       ((ClosedRange (1::Int) 10) `intersect` (OpenRange 50 (60 :: Int)))       `shouldBe` (coRec NoIntersection)+    it "endpoints overlap but open/closed" $ do+      let r1, r2 :: Range Int+          r1 = ClosedRange 3 6+          r2 = Range (Open 1) (Open 3)+        in (r1 `intersects` r2) `shouldBe` False     -- it "closed intersect open" $     --   ((OpenRange 1 (10 :: Int)) `intersect` (ClosedRange 10 (12 :: Int)))     --   `shouldBe` (coRec NoIntersection)
+ test/Data/RealNumber/RationalSpec.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DataKinds #-}+module Data.RealNumber.RationalSpec where++import           Data.RealNumber.Rational+import           Test.Hspec+import           Test.QuickCheck++type R = RealNumber 5++spec :: Spec+spec = do+  describe "Read/Show" $ do+    it "read basic" $ do+      read (show (1::R)) `shouldBe` (1::R)+      read (show (negate 1::R)) `shouldBe` negate (1::R)+    it "read nested" $ do+      read (show (Just (1::R))) `shouldBe` Just (1::R)+      read (show (Just (negate 1::R))) `shouldBe` Just (negate (1::R))+    specify "significant digits" $ do+      show (0.12345::RealNumber 2) `shouldBe` "0.12~"+      show (0.12345::RealNumber 5) `shouldBe` "0.12345"+    it "should discard tail" $ do+      read (show (0.12345::RealNumber 2)) `shouldBe` (0.12 ::R)+      reads "0.12345~" `shouldBe` [(0.12::RealNumber 2, "")]+