utility/config.h: Support GEODE_FLATTEN on clang
Speed up UnionFind by around 30%

This replaces path compression with path halving, and reuses the parents
array to store ranks.  The latter avoids an extra array, but strangely
did not help by itself.
TriangleSoup: Add triangle_edges()
utility/config: Give GEODE_UNREACHABLE optional arguments

These are used only in debug mode.
math/numeric_limits: Expose some integer numeric limits
mesh/io: Fix assertions
platonic: Add octahedron_mesh()
Nested: Add const_()
RawField: Allow conversion from empty tuples
array/reversed: Add an expression template reversing an array
Add symbolically perturbed triangle mesh CSG

The cutting and retriangulation portions of the code operate on
triangle soup, so they can be run on any bag of triangles.  Depth
calculation and pruning, of course, require closed meshes.

Notes:

1. There is now a perturbed_construct routine analogous to perturbed_sign
   which makes writing construction routines easier and less error prone.
   Since it is available essentially for free and often useful,
   perturbed_construct also returns the perturbed sign of the denominator.

2. The CHECK feature is factored out into an exact/debug.h header.

3. Retriangulation of cut faces works in two phases, first triangulating
   all edge-face vertices inside the face and then incrementally inserting
   all face-face edges in random order similar to constrained Delaunay.
   Face-face-face vertices are generated as needed during this process.
   I believe that Shewchuck's proof that random edge insertion is
   O(n log^2 n) time still holds, though of course "n" may be quadratic
   if many face-face edges intersect.  The triangulation algorithm is
   factored out into the simple_triangulate.h header, which uses a policy
   class to answer geometry queries.  A naive policy class using interval
   arithmetic only is used to independently test triangulation by itself.