These are a few routines to support a class of test where we construct a n-dimensional complex in flat n-dimensions with Cartesian coordinates surrounding the complex. The zone logic is unaware of this and indeed lacks access to these coordinates, yet is charged in transmitting a ray in a straight line, and even tracking its affine parameter. Just now I can’t imagine a zone bug that such tests fail to catch. When we measure curvatures within the complex, we may embed them in a space of some known curvature.

top refers to a list of vertex lists which defines the topology of the complex under test. Its logic is described here. embd is the array of cartesian coordinates of the respective vertices, as embedded; the global vertex number indexes into embd.

mix (top, embd, sbl) perm returns another (top, embd, sbl) with vertex numbers permuted by perm where sbl is a list of vertex number lists which the test code must track under this permutation. There are many efficient but confusing pieces of code that depend on which vertex of a zone or facet serves as origin of the bcc coordinates. These permutations stress that code so as to reveal bugs.

Morhogenesis calls nz embd vl once per zone with vl for that zone; it is about the simplest possible code to call Zone.newz for each zone described by vl. nz deals with global vertex numbers which it hides from Zone.newz. nz returns a pair:

nz is a specialized routine for the glue logic. Glue logic returns bl which is the leftover facet access for the boundary thru which we can inject a ray.

prep, receives the embedding info and a vertex list such as returned by Glue.morphgen. prep computes two coordinate transformations for a facet: (in, out), into the complex, and out of the complex, via some facet specified by the vertex list. Each transformation takes and returns a pair of vectors: (position * direction), called a Cray or Fray here, suitable for locating a ray. The Cray is in global Cartesian coordinates of the embedding space and the Fray is in facet bcc coordinates. The first function (in) converts from coordinates of the embedding space to those of the facet, sign flipped already. The 2nd goes the other way. In prep, cti is the coordinate transformation from embedding space coordinates to facet coordinates. cto is the inverse matrix. The direction of the normal basis vector depends on the orientation of the facet. prep provides two transformations for a facet that belongs to the boundary of the complex. I use it now for inserting rays into the complex and catching them as they emerge.

prep is at the interface of two abstracted types: Jig.ray and Zone.fray. Having access to embd it is competent to translate between these and needs to manhandle their innards. I suppose that we will have to leak the innards of Zone.fray to Jig.

The invocation jig embd bl inf outf takes the Cartesian vertex coordinates, embd, the yield of morphgen, choices of facets for signal injection and reception, inf and outf, and returns a record {lray; lcurl} of two functions. lray takes and returns values of type cray; it invokes the ray logic. lray is of type curlp and takes performs a curl query about a partially exposed bone.

The type of the in transformation is Cray -> Fray and a synopsis is:

(p, d) -> (I(p - facetOrg), Id)
Where I is the linear transformation implemented by matrix cti.

cm is an internal routine that computes distances between vertices in the Cartesian coordinates. When sg is set to [|-1.; 1.; 1.; 1.|] we obtain a Minkowski metric. The test cases now fail for Minkowski.


In bug (now fixed) p is (1/3, 1/3, 1/3) which is the center of the facet which is the hull of ((0, 0, 1), (1, 0, 0), (0, 1, 0)). This is also the global ordering of the vertices of the facet and so (0, 1, 0) is the origin for the facet (facetOrg). p - facetOrg = (1/3, −2/3, 1/3) which must be a linear combination of the two facet basis vectors: {(0, −1, 1), (1, −1, 0)}. The other basis vector is out of the plane of the facet and should not be needed to express p. Indeed p = (the sum of the two basis vectors)/3 and the Fray should be ((1/3, 1/3, 0), ---), which is not what my code computes.

Proceeding from theory, the three facet basis vectors, expressed in Cartesian coordinates should be ((0, −1, 1), (1, −1, 0), (−1, −1, −1)3−1/2). The matrix cto should be the transpose of this very matrix. (There remains confusion on the sign of the normal basis vector.) inf;; yields [0; 3; 4] contradicting my identification of the ingress facet. Bug in test case definition!


The code Jig.jig illustrates a problem in that cti is the inverse of a matrix and is computed sometime when it is not needed. Using memoizing logic would avoid this but I don't want to pay that hair here. Haskell solves this under the covers.

2009 November 24 Bug

Test ji21 produces [|[|-1.; 0.|]; [|0.; 1.|]|] just now where it should reproduce the input: [|[|1.; 0.|]; [|0.; 1.|]|]. I think the most relevant recent change was fliping the sign of the normal facet coordinates into the Zone routine cvz2f. The print statement with tag “xr” catches vectors, [| 0.; -1. |] [| 1.; 0. |], just after they have been converted to facet coordinates by cvz2f. Except for the sign flip this would be wrong because the facet normal is inwards (to the right) which is the same direction as the first carried vector. That puts the onus on Jig to flip the sign of the emerging curl probe due to the (mis) orientation of the facet where the probe emerges. This is fixed in the grotesque code that flips the sign of the right column of ctoX.