aboutsummaryrefslogtreecommitdiff
path: root/ic-reals-6.3/base/TenXY.c
diff options
context:
space:
mode:
Diffstat (limited to 'ic-reals-6.3/base/TenXY.c')
-rw-r--r--ic-reals-6.3/base/TenXY.c1752
1 files changed, 1752 insertions, 0 deletions
diff --git a/ic-reals-6.3/base/TenXY.c b/ic-reals-6.3/base/TenXY.c
new file mode 100644
index 0000000..7199966
--- /dev/null
+++ b/ic-reals-6.3/base/TenXY.c
@@ -0,0 +1,1752 @@
+/*
+ * Copyright (C) 2000, Imperial College
+ *
+ * This file is part of the Imperial College Exact Real Arithmetic Library.
+ * See the copyright notice included in the distribution for conditions
+ * of use.
+ */
+
+#include <stdio.h>
+#include "real.h"
+#include "real-impl.h"
+
+/*
+ * Functions for allocating and manipulating tensor LFTs in the heap.
+ */
+
+void setTenXY_Y_MethodSigned(TenXY *);
+void setTenXY_X_MethodSigned(TenXY *);
+void setTenXY_Y_MethodUnsigned(TenXY *);
+void setTenXY_X_MethodUnsigned(TenXY *);
+
+void absorbDigsXIntoTenXY_X(TenXY *);
+void absorbDigsXIntoTenXY_Y(TenXY *);
+void createUnsignedStreamForTenXY(TenXY *);
+
+TenXY *
+allocTenXY()
+{
+ TenXY *tenXY;
+
+ if ((tenXY = (TenXY *) malloc (sizeof(TenXY))) == NULL)
+ Error(FATAL, E_INT, "allocTenXY", "malloc failed");
+
+#ifdef DAVINCI
+ newNodeId(tenXY);
+#else
+#ifdef TRACE
+ newNodeId(tenXY);
+#endif
+#endif
+ tenXY->tag.type = TENXY;
+ tenXY->tag.dumped = FALSE;
+ tenXY->strm = (Real) NULL;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newNode(tenXY, TENXY);
+ endGraphUpdate();
+#endif
+
+ return tenXY;
+}
+
+/*
+ * The following function allocates a tensor, fills in the tensor
+ * entries and sets the arguments to the tensors.
+ *
+ * There is code here for eagerly reducing a tensor against vector and
+ * matrix arguments. Eager reduction has the advantage that it reduces
+ * the amount of garbage created in the heap. For the time being, however,
+ * reduction is disabled since there are functions which call this function
+ * and assume the result they get back is genuinely a tensor. With reduction
+ * it may return a tensor, matrix or vector.
+ */
+
+Real
+tensor_Int(Real x, Real y,
+ int a, int b, int c, int d,
+ int e, int f, int g, int h)
+{
+ TenXY *tenXY;
+
+#ifdef LATER
+ /*
+ * If either or both of the arguments are vectors, then there is room
+ * for reduction.
+ */
+ if (x->gen.tag.type == VECTOR || y->gen.tag.type == VECTOR) {
+ mpz_init_set_si(bigTmpTen[0][0], a);
+ mpz_init_set_si(bigTmpTen[0][1], b);
+ mpz_init_set_si(bigTmpTen[1][0], c);
+ mpz_init_set_si(bigTmpTen[1][1], d);
+ mpz_init_set_si(bigTmpTen[2][0], e);
+ mpz_init_set_si(bigTmpTen[2][1], f);
+ mpz_init_set_si(bigTmpTen[3][0], g);
+ mpz_init_set_si(bigTmpTen[3][1], h);
+
+ if (x->gen.tag.type == VECTOR) {
+ multVectorPairTimesVector(bigTmpTen[0], bigTmpTen[2], x->vec.vec);
+ multVectorPairTimesVector(bigTmpTen[1], bigTmpTen[3], x->vec.vec);
+ }
+
+ if (y->gen.tag.type == VECTOR) {
+ multVectorPairTimesVector(bigTmpTen[0], bigTmpTen[1], y->vec.vec);
+ multVectorPairTimesVector(bigTmpTen[2], bigTmpTen[3], y->vec.vec);
+ }
+
+ if (x->gen.tag.type == VECTOR) {
+ if (y->gen.tag.type == VECTOR)
+ return vector_Z(bigTmpTen[0][0], bigTmpTen[0][1]);
+ else
+ return matrix_Z(y, bigTmpTen[0][0], bigTmpTen[0][1],
+ bigTmpTen[1][0], bigTmpTen[1][1]);
+ }
+ else { /* then y->gen.tag.type == VECTOR */
+ return matrix_Z(x, bigTmpTen[0][0], bigTmpTen[0][1],
+ bigTmpTen[2][0], bigTmpTen[2][1]);
+ }
+ }
+#endif
+
+ /*
+ * So now we know we will end up with a tensor, so we allocate one.
+ */
+ tenXY = allocTenXY();
+
+ mpz_init_set_si(tenXY->ten[0][0], a);
+ mpz_init_set_si(tenXY->ten[0][1], b);
+ mpz_init_set_si(tenXY->ten[1][0], c);
+ mpz_init_set_si(tenXY->ten[1][1], d);
+ mpz_init_set_si(tenXY->ten[2][0], e);
+ mpz_init_set_si(tenXY->ten[2][1], f);
+ mpz_init_set_si(tenXY->ten[3][0], g);
+ mpz_init_set_si(tenXY->ten[3][1], h);
+
+ /* remove powers of 2 from the tensor */
+ normalizeTensor(tenXY->ten);
+
+ /* make the tensor positive if it is negative (no entries > 0) */
+ if (tensorSign(tenXY->ten) < 0)
+ negateTensor(tenXY->ten);
+
+ tenXY->x = x;
+ tenXY->y = y;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToXChild(tenXY, x);
+ newEdgeToYChild(tenXY, y);
+ endGraphUpdate();
+#endif
+
+#ifdef LATER
+ /*
+ * Now we eagerly consume any matrix which follows.
+ */
+ if (x->gen.tag.type == MATX) {
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[2], x->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[1], tenXY->ten[3], x->matX.mat);
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, x->matX.x);
+ endGraphUpdate();
+#endif
+ tenXY->x = x->matX.x;
+ }
+
+ /*
+ * Do the same as the above on the y side now.
+ */
+ if (y->gen.tag.type == MATX) {
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[1], y->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[2], tenXY->ten[3], y->matX.mat);
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, y->matX.x);
+ endGraphUpdate();
+#endif
+ tenXY->y = y->matX.x;
+ }
+#endif
+
+ /*
+ * A TenXY is signed if the there are entries in the tensor of different
+ * signs or if either argument to the TenXY is signed.
+ */
+ if (tenXY->x->gen.tag.isSigned
+ || tenXY->y->gen.tag.isSigned
+ || tensorSign(tenXY->ten) == 0)
+ tenXY->tag.isSigned = TRUE;
+
+ if (tenXY->x->gen.tag.isSigned)
+ setTenXY_X_MethodSigned(tenXY);
+ else
+ setTenXY_X_MethodUnsigned(tenXY);
+
+ if (tenXY->y->gen.tag.isSigned)
+ setTenXY_Y_MethodSigned(tenXY);
+ else
+ setTenXY_Y_MethodUnsigned(tenXY);
+
+ return (Real) tenXY;
+}
+
+Real
+tensor_Z(Real x, Real y,
+ mpz_t a, mpz_t b, mpz_t c, mpz_t d,
+ mpz_t e, mpz_t f, mpz_t g, mpz_t h)
+{
+ TenXY *tenXY;
+
+ /*
+ * So now we know we will end up with a tensor, so we allocate one.
+ */
+ tenXY = allocTenXY();
+
+ mpz_init_set(tenXY->ten[0][0], a);
+ mpz_init_set(tenXY->ten[0][1], b);
+ mpz_init_set(tenXY->ten[1][0], c);
+ mpz_init_set(tenXY->ten[1][1], d);
+ mpz_init_set(tenXY->ten[2][0], e);
+ mpz_init_set(tenXY->ten[2][1], f);
+ mpz_init_set(tenXY->ten[3][0], g);
+ mpz_init_set(tenXY->ten[3][1], h);
+
+ /* remove powers of 2 from the tensor */
+ normalizeTensor(tenXY->ten);
+
+ /* make the tensor positive if it is negative (no entries > 0) */
+ if (tensorSign(tenXY->ten) < 0)
+ negateTensor(tenXY->ten);
+
+ tenXY->x = x;
+ tenXY->y = y;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToXChild(tenXY, x);
+ newEdgeToYChild(tenXY, y);
+ endGraphUpdate();
+#endif
+
+ /*
+ * A TenXY is signed if the there are entries in the tensor of different
+ * signs or if either argument to the TenXY is signed.
+ */
+ if (tenXY->x->gen.tag.isSigned
+ || tenXY->y->gen.tag.isSigned
+ || tensorSign(tenXY->ten) == 0)
+ tenXY->tag.isSigned = TRUE;
+
+ if (tenXY->x->gen.tag.isSigned)
+ setTenXY_X_MethodSigned(tenXY);
+ else
+ setTenXY_X_MethodUnsigned(tenXY);
+
+ if (tenXY->y->gen.tag.isSigned)
+ setTenXY_Y_MethodSigned(tenXY);
+ else
+ setTenXY_Y_MethodUnsigned(tenXY);
+
+ return (Real) tenXY;
+}
+
+void
+force_To_TenXY_X_From_DigsX_Entry()
+{
+ TenXY *tenXY;
+ DigsX *digsX;
+ int digitsNeeded;
+ void force_To_TenXY_X_From_DigsX_Cont();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+ digsX = (DigsX *) tenXY->x;
+
+ PUSH_3(force_To_TenXY_X_From_DigsX_Cont, tenXY, digitsNeeded);
+
+ /*
+ * See if the source has the number of digits we need. If not,
+ * then force the remaining.
+ */
+ if (digsX->count < (unsigned int)digitsNeeded)
+ PUSH_3(digsX->force, digsX, digitsNeeded - digsX->count);
+}
+
+void
+force_To_TenXY_X_From_DigsX_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ absorbDigsXIntoTenXY_X(tenXY);
+}
+
+void
+force_To_TenXY_X_From_DigsX_Signed()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_X_From_DigsX_Entry();
+
+ tenXY = (TenXY *) POP;
+ tenXY->forceX = force_To_TenXY_X_From_DigsX_Entry;
+}
+
+void
+force_To_TenXY_Y_From_DigsX_Signed()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_Y_From_DigsX_Entry();
+
+ tenXY = (TenXY *) POP;
+ tenXY->forceY = force_To_TenXY_Y_From_DigsX_Entry;
+}
+
+/*
+ * When a tensor absorbs a vector, the tensor reduces to a matrix. We do this
+ * in place. That is, we overwrite the tensor with a matrix. We do this
+ * since the tensor might be shared. It might waste a bit of space
+ * but the garbage collector will deal with this (eventually).
+ *
+ * Note that the node drawn by daVinci still has type tensor but this
+ * doesn't matter.
+ */
+void
+force_To_TenXY_X_From_Vec()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ mpz_t a, b, c, d; /* temporary storage while we clobber the TenXY */
+ Real strm; /* temporary storage again */
+ int digitsNeeded;
+ int totalEmitted;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ multVectorPairTimesVector(tenXY->ten[0], tenXY->ten[2], tenXY->x->vec.vec);
+ multVectorPairTimesVector(tenXY->ten[1], tenXY->ten[3], tenXY->x->vec.vec);
+
+ a[0] = tenXY->ten[0][0][0];
+ b[0] = tenXY->ten[0][1][0];
+ c[0] = tenXY->ten[1][0][0];
+ d[0] = tenXY->ten[1][1][0];
+ strm = tenXY->strm;
+ totalEmitted = tenXY->totalEmitted;
+
+ mpz_clear(tenXY->ten[2][0]);
+ mpz_clear(tenXY->ten[2][1]);
+ mpz_clear(tenXY->ten[3][0]);
+ mpz_clear(tenXY->ten[3][1]);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ endGraphUpdate();
+#endif
+
+ matX = (MatX *) tenXY;
+ matX->tag.type = MATX;
+ matX->x = tenXY->y;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToOnlyChild(matX, matX->x);
+ endGraphUpdate();
+#endif
+
+ matX->mat[0][0][0] = a[0];
+ matX->mat[0][1][0] = b[0];
+ matX->mat[1][0][0] = c[0];
+ matX->mat[1][1][0] = d[0];
+ normalizeMatrix(matX->mat);
+ matX->strm = strm;
+ matX->totalEmitted = totalEmitted;
+
+ setMatXMethodUnsigned(matX);
+}
+
+/*
+ * When a tensor absorbs a vector, the tensor reduces to a matrix. We do this
+ * in place. That is, we overwrite the tensor with a matrix. We do this
+ * since the tensor might be shared. It might waste a bit of space
+ * but the garbage collector will deal with this (eventually).
+ *
+ * Note that the node drawn by daVinci still has type tensor but this
+ * doesn't matter.
+ */
+void
+force_To_TenXY_Y_From_Vec()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ mpz_t a, b, c, d; /* temporary storage while we clobber the TenXY */
+ Real strm; /* temporary storage again */
+ int digitsNeeded;
+ int totalEmitted;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ multVectorPairTimesVector(tenXY->ten[0], tenXY->ten[1], tenXY->y->vec.vec);
+ multVectorPairTimesVector(tenXY->ten[2], tenXY->ten[3], tenXY->y->vec.vec);
+
+ a[0] = tenXY->ten[0][0][0];
+ b[0] = tenXY->ten[0][1][0];
+ c[0] = tenXY->ten[2][0][0];
+ d[0] = tenXY->ten[2][1][0];
+ strm = tenXY->strm;
+ totalEmitted = tenXY->totalEmitted;
+
+ mpz_clear(tenXY->ten[1][0]);
+ mpz_clear(tenXY->ten[1][1]);
+ mpz_clear(tenXY->ten[3][0]);
+ mpz_clear(tenXY->ten[3][1]);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ endGraphUpdate();
+#endif
+
+ matX = (MatX *) tenXY;
+ matX->tag.type = MATX;
+ matX->x = tenXY->x;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToOnlyChild(matX, matX->x);
+ endGraphUpdate();
+#endif
+ matX->mat[0][0][0] = a[0];
+ matX->mat[0][1][0] = b[0];
+ matX->mat[1][0][0] = c[0];
+ matX->mat[1][1][0] = d[0];
+ normalizeMatrix(matX->mat);
+ matX->strm = strm;
+ matX->totalEmitted = totalEmitted;
+
+ setMatXMethodUnsigned(matX);
+}
+
+void
+force_To_TenXY_X_From_MatX()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+ void force_To_TenXY_X_From_Vec();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ if (tenXY->x->gen.tag.type == VECTOR) {
+ PUSH_3(force_To_TenXY_X_From_Vec, tenXY, digitsNeeded);
+ return;
+ }
+
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[2], tenXY->x->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[1], tenXY->ten[3], tenXY->x->matX.mat);
+ normalizeTensor(tenXY->ten);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->matX.x);
+ endGraphUpdate();
+#endif
+ tenXY->x = tenXY->x->matX.x;
+ setTenXY_X_MethodUnsigned(tenXY);
+}
+
+void
+force_To_TenXY_Y_From_MatX()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+ void force_To_TenXY_Y_From_Vec();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ if (tenXY->y->gen.tag.type == VECTOR) {
+ PUSH_3(force_To_TenXY_Y_From_Vec, tenXY, digitsNeeded);
+ return;
+ }
+
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[1], tenXY->y->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[2], tenXY->ten[3], tenXY->y->matX.mat);
+ normalizeTensor(tenXY->ten);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->matX.x);
+ endGraphUpdate();
+#endif
+ tenXY->y = tenXY->y->matX.x;
+ setTenXY_Y_MethodUnsigned(tenXY);
+}
+
+/*
+ * This forces information (ie digits, not a sign) from one tensor into
+ * the x argument of another. It is assumed that the argument is unsigned,
+ * otherwise it would already have changed into a SignX or DigsX.
+ */
+void
+force_To_TenXY_X_From_TenXY()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+ void force_To_TenXY_X_From_DigsX_Entry();
+ void force_To_TenXY_X_From_MatX();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ if (tenXY->x->gen.tag.type != TENXY) {
+ PUSH_3(force_To_TenXY_X_From_MatX, tenXY, digitsNeeded);
+ return;
+ }
+
+ createUnsignedStreamForTenXY((TenXY *) tenXY->x);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->tenXY.strm);
+ endGraphUpdate();
+#endif
+
+ tenXY->x = tenXY->x->tenXY.strm;
+ tenXY->forceX = force_To_TenXY_X_From_DigsX_Entry;
+ PUSH_3(tenXY->forceX, tenXY, digitsNeeded);
+}
+
+/*
+ * This forces information (ie digits, not a sign) from one tensor into
+ * the y argument of another. It is assumed that the argument is unsigned,
+ * otherwise it would already have changed into a SignX or DigsX.
+ */
+void
+force_To_TenXY_Y_From_TenXY()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+ void force_To_TenXY_Y_From_DigsX_Entry();
+ void force_To_TenXY_Y_From_MatX();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ if (tenXY->y->gen.tag.type != TENXY) {
+ PUSH_3(force_To_TenXY_Y_From_MatX, tenXY, digitsNeeded);
+ return;
+ }
+
+ createUnsignedStreamForTenXY((TenXY *) tenXY->y);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->tenXY.strm);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->tenXY.strm;
+ tenXY->forceY = force_To_TenXY_Y_From_DigsX_Entry;
+ PUSH_3(tenXY->forceY, tenXY, digitsNeeded);
+}
+
+void
+force_To_TenXY_Y_From_DigsX_Entry()
+{
+ TenXY *tenXY;
+ DigsX *digsX;
+ int digitsNeeded;
+ void force_To_TenXY_Y_From_DigsX_Cont();
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+ digsX = (DigsX *) tenXY->y;
+
+ PUSH_3(force_To_TenXY_Y_From_DigsX_Cont, tenXY, digitsNeeded);
+
+ /*
+ * See if the source has the number of digits we need. If not,
+ * then force the remaining.
+ */
+ if (digsX->count < (unsigned int)digitsNeeded)
+ PUSH_3(digsX->force, digsX, digitsNeeded - digsX->count);
+}
+
+void
+force_To_TenXY_Y_From_DigsX_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ absorbDigsXIntoTenXY_Y(tenXY);
+}
+
+/*
+ * In some cases when we generate a chain of tensors, the tensors
+ * themselves are not refining. What we have to do is force information
+ * from the argument until the tensor is refining.
+ *
+ * If the tensor is not refining, we force a digit from it's argument
+ * and push a continuation to check again.
+ */
+void
+force_To_TenXY_X_Until_Refining()
+{
+ TenXY *tenXY;
+ int sgn;
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->tag.type != TENXY)
+ return;
+
+ sgn = tensorSign(tenXY->ten);
+
+ if (sgn > 0) /* tensor is refining and entries positive */
+ return;
+
+ if (sgn < 0) { /* tensor is refining and entries negative */
+ negateTensor(tenXY->ten);
+ return;
+ }
+
+ PUSH_2(force_To_TenXY_X_Until_Refining, tenXY);
+ PUSH_3(tenXY->forceX, tenXY, defaultForceCount);
+}
+
+void
+force_To_TenXY_X_From_Alt_Entry()
+{
+ TenXY *tenXY;
+ void force_To_Alt_Entry();
+ void force_To_TenXY_X_From_Alt_Cont();
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ PUSH_3(force_To_TenXY_X_From_Alt_Cont, tenXY, digitsNeeded);
+
+ /*
+ * If alt->redirect is not valid (equals NULL) then the value of
+ * the conditional has not been determined so we need to force it.
+ */
+ if (tenXY->x->alt.redirect == NULL)
+ PUSH_2(force_To_Alt_Entry, tenXY->x);
+}
+
+void
+force_To_TenXY_X_From_Alt_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->alt.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->x = tenXY->x->alt.redirect;
+ setTenXY_X_MethodUnsigned(tenXY);
+ PUSH_3(tenXY->forceX, tenXY, digitsNeeded);
+}
+
+void
+force_To_TenXY_X_From_Cls_Entry()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_X_From_Cls_Cont();
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ PUSH_3(force_To_TenXY_X_From_Cls_Cont, tenXY, digitsNeeded);
+
+ /*
+ * If cls->redirect is not valid (equals NULL) then the value of
+ * the closure has not been determined so we need to force it.
+ */
+ if (tenXY->x->cls.redirect == NULL)
+ PUSH_2(tenXY->x->cls.force, tenXY->x);
+}
+
+void
+force_To_TenXY_X_From_Cls_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->cls.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->x = tenXY->x->cls.redirect;
+ setTenXY_X_MethodUnsigned(tenXY);
+ PUSH_3(tenXY->forceX, tenXY, digitsNeeded);
+}
+
+void
+force_To_TenXY_X_From_Alt_Signed_Entry()
+{
+ TenXY *tenXY;
+ void force_To_Alt_Entry();
+ void force_To_TenXY_X_From_Alt_Signed_Cont();
+
+ tenXY = (TenXY *) POP;
+
+ PUSH_2(force_To_TenXY_X_From_Alt_Signed_Cont, tenXY);
+
+ /*
+ * If alt->redirect is not valid (equals NULL) then the value of
+ * the conditional has not been determined so we need to force it.
+ */
+ if (tenXY->x->alt.redirect == NULL)
+ PUSH_2(force_To_Alt_Entry, tenXY->x);
+}
+
+void
+force_To_TenXY_X_From_Alt_Signed_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->alt.redirect);
+ endGraphUpdate();
+#endif
+ tenXY->x = tenXY->x->alt.redirect;
+ setTenXY_X_MethodSigned(tenXY);
+
+ PUSH_2(tenXY->forceX, tenXY);
+}
+
+void
+force_To_TenXY_X_From_Cls_Signed_Entry()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_X_From_Cls_Signed_Cont();
+
+ tenXY = (TenXY *) POP;
+
+ PUSH_2(force_To_TenXY_X_From_Cls_Signed_Cont, tenXY);
+
+ /*
+ * If cls->redirect is not valid (equals NULL) then the value of
+ * the conditional has not been determined so we need to force it.
+ */
+ if (tenXY->x->cls.redirect == NULL)
+ PUSH_2(tenXY->x->cls.force, tenXY->x);
+}
+
+void
+force_To_TenXY_X_From_Cls_Signed_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->cls.redirect);
+ endGraphUpdate();
+#endif
+ tenXY->x = tenXY->x->cls.redirect;
+ setTenXY_X_MethodSigned(tenXY);
+
+ PUSH_2(tenXY->forceX, tenXY);
+}
+
+void
+force_To_TenXY_Y_From_Alt_Entry()
+{
+ TenXY *tenXY;
+ void force_To_Alt_Entry();
+ void force_To_TenXY_Y_From_Alt_Cont();
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ PUSH_3(force_To_TenXY_Y_From_Alt_Cont, tenXY, digitsNeeded);
+
+ /*
+ * If alt->redirect is not valid (equals NULL) then the value of
+ * the conditional has not been determined so we need to force it.
+ */
+ if (tenXY->y->alt.redirect == NULL)
+ PUSH_2(force_To_Alt_Entry, tenXY->y);
+}
+
+void
+force_To_TenXY_Y_From_Alt_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->alt.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->alt.redirect;
+ setTenXY_Y_MethodUnsigned(tenXY);
+ PUSH_3(tenXY->forceY, tenXY, digitsNeeded);
+}
+
+void
+force_To_TenXY_Y_From_Cls_Entry()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_Y_From_Cls_Cont();
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+ PUSH_3(force_To_TenXY_Y_From_Cls_Cont, tenXY, digitsNeeded);
+
+ /*
+ * If cls->redirect is not valid (equals NULL) then the value of
+ * the closure has not been determined so we need to force it.
+ */
+ if (tenXY->y->cls.redirect == NULL)
+ PUSH_2(tenXY->y->cls.force, tenXY->y);
+}
+
+void
+force_To_TenXY_Y_From_Cls_Cont()
+{
+ TenXY *tenXY;
+ int digitsNeeded;
+
+ tenXY = (TenXY *) POP;
+ digitsNeeded = (int) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->cls.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->cls.redirect;
+ setTenXY_Y_MethodUnsigned(tenXY);
+ PUSH_3(tenXY->forceY, tenXY, digitsNeeded);
+}
+
+void
+force_To_TenXY_Y_From_Alt_Signed_Entry()
+{
+ TenXY *tenXY;
+ void force_To_Alt_Entry();
+ void force_To_TenXY_Y_From_Alt_Signed_Cont();
+
+ tenXY = (TenXY *) POP;
+
+ PUSH_2(force_To_TenXY_Y_From_Alt_Signed_Cont, tenXY);
+
+ /*
+ * If alt->redirect is not valid (equals NULL) then the value of
+ * the conditional has not been determined so we need to force it.
+ */
+ if (tenXY->y->alt.redirect == NULL)
+ PUSH_2(force_To_Alt_Entry, tenXY->y);
+}
+
+void
+force_To_TenXY_Y_From_Alt_Signed_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->alt.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->alt.redirect;
+ setTenXY_Y_MethodSigned(tenXY);
+ PUSH_2(tenXY->forceY, tenXY);
+}
+
+void
+force_To_TenXY_Y_From_Cls_Signed_Entry()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_Y_From_Cls_Signed_Cont();
+
+ tenXY = (TenXY *) POP;
+
+ PUSH_2(force_To_TenXY_Y_From_Cls_Signed_Cont, tenXY);
+
+ /*
+ * If cls->redirect is not valid (equals NULL) then the value of
+ * the closure has not been determined so we need to force it.
+ */
+ if (tenXY->y->cls.redirect == NULL)
+ PUSH_2(tenXY->y->cls.force, tenXY->y);
+}
+
+void
+force_To_TenXY_Y_From_Cls_Signed_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->cls.redirect);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->cls.redirect;
+ setTenXY_Y_MethodSigned(tenXY);
+ PUSH_2(tenXY->forceY, tenXY);
+}
+
+void
+absorbSignIntoTenXY_Y(TenXY *tenXY)
+{
+ absorbSignIntoVectorPair(tenXY->ten[0], tenXY->ten[1],
+ tenXY->y->signX.tag.value);
+ absorbSignIntoVectorPair(tenXY->ten[2], tenXY->ten[3],
+ tenXY->y->signX.tag.value);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->signX.x);
+ endGraphUpdate();
+#endif
+ tenXY->y = tenXY->y->signX.x;
+ setTenXY_Y_MethodUnsigned(tenXY);
+}
+
+void
+absorbSignIntoTenXY_X(TenXY *tenXY)
+{
+ absorbSignIntoVectorPair(tenXY->ten[0], tenXY->ten[2],
+ tenXY->x->signX.tag.value);
+ absorbSignIntoVectorPair(tenXY->ten[1], tenXY->ten[3],
+ tenXY->x->signX.tag.value);
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->signX.x);
+ endGraphUpdate();
+#endif
+ tenXY->x = tenXY->x->signX.x;
+ setTenXY_X_MethodUnsigned(tenXY);
+}
+
+void
+absorbDigsXIntoTenXY_Y(TenXY *tenXY)
+{
+ DigsX *digsX;
+ SmallMatrix smallAccumMat;
+
+ digsX = (DigsX *) tenXY->y;
+
+ /*
+ * Accumulate the digits into a matrix (large or small integers)
+ * and augment the tensor with the information.
+ */
+ if (digsX->count > 0) {
+#ifdef PACK_DIGITS
+ if (digsX->count <= DIGITS_PER_WORD) {
+ makeSmallMatrixFromDigits(smallAccumMat, digsX);
+ multVectorPairTimesSmallMatrix(tenXY->ten[0], tenXY->ten[1],
+ smallAccumMat);
+ multVectorPairTimesSmallMatrix(tenXY->ten[2], tenXY->ten[3],
+ smallAccumMat);
+ }
+ else {
+#endif
+ makeMatrixFromDigits(bigTmpMat, digsX);
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[1], bigTmpMat);
+ multVectorPairTimesMatrix(tenXY->ten[2], tenXY->ten[3], bigTmpMat);
+#ifdef PACK_DIGITS
+ }
+#endif
+ normalizeTensor(tenXY->ten);
+ tenXY->y = digsX->x;
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, digsX);
+ newEdgeToYChild(tenXY, digsX->x);
+ endGraphUpdate();
+#endif
+ }
+
+#ifdef TRACE
+ debugp("absorbDigsXIntoTenXY_Y",
+ "%x %x absorbed=%d\n",
+ (unsigned) tenXY,
+ (unsigned) digsX,
+ digsX->count);
+#endif
+}
+
+void
+absorbDigsXIntoTenXY_X(TenXY *tenXY)
+{
+ DigsX *digsX;
+ SmallMatrix smallAccumMat;
+
+ digsX = (DigsX *) tenXY->x;
+
+ /*
+ * Now accumulate the digits into a matrix (large or small integers)
+ * and augment the tensor with the information.
+ */
+ if (digsX->count > 0) {
+#ifdef PACK_DIGITS
+ if (digsX->count <= DIGITS_PER_WORD) {
+ makeSmallMatrixFromDigits(smallAccumMat, digsX);
+ multVectorPairTimesSmallMatrix(tenXY->ten[0], tenXY->ten[2],
+ smallAccumMat);
+ multVectorPairTimesSmallMatrix(tenXY->ten[1], tenXY->ten[3],
+ smallAccumMat);
+ }
+ else {
+#endif
+ makeMatrixFromDigits(bigTmpMat, digsX);
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[2], bigTmpMat);
+ multVectorPairTimesMatrix(tenXY->ten[1], tenXY->ten[3], bigTmpMat);
+#ifdef PACK_DIGITS
+ }
+#endif
+ normalizeTensor(tenXY->ten);
+ tenXY->x = digsX->x;
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, digsX);
+ newEdgeToXChild(tenXY, digsX->x);
+ endGraphUpdate();
+#endif
+ }
+
+#ifdef TRACE
+ debugp("absorbDigsXIntoTenXY_X",
+ "%x %x absorbed=%d\n",
+ (unsigned) tenXY,
+ (unsigned) digsX,
+ digsX->count);
+#endif
+}
+
+void
+createSignedStreamForTenXY(TenXY *tenXY)
+{
+ Real r;
+ void force_To_SignX_From_TenXY_Entry();
+
+ if (tenXY->strm == NULL) {
+ r = tensor_Z(tenXY->x, tenXY->y,
+ tenXY->ten[0][0], tenXY->ten[0][1],
+ tenXY->ten[1][0], tenXY->ten[1][1],
+ tenXY->ten[2][0], tenXY->ten[2][1],
+ tenXY->ten[3][0], tenXY->ten[3][1]);
+ tenXY->strm = (Real) allocSignX(r, SIGN_UNKN);
+#ifdef DAVINCI
+ beginGraphUpdate();
+ drawEqEdge(tenXY, tenXY->strm);
+ endGraphUpdate();
+#endif
+ }
+}
+
+void
+createUnsignedStreamForTenXY(TenXY *tenXY)
+{
+ DigsX *digsX;
+ Real r;
+ void force_To_DigsX_From_TenXY_Entry();
+
+ if (tenXY->strm == NULL) {
+ if (tenXY->tag.isSigned)
+ Error(FATAL, E_INT, "createUnsignedStreamForTenXY",
+ "creating unsigned stream for signed tensor");
+ else {
+ r = tensor_Z(tenXY->x, tenXY->y,
+ tenXY->ten[0][0], tenXY->ten[0][1],
+ tenXY->ten[1][0], tenXY->ten[1][1],
+ tenXY->ten[2][0], tenXY->ten[2][1],
+ tenXY->ten[3][0], tenXY->ten[3][1]);
+ digsX = allocDigsX();
+ digsX->x = (Real) r;
+ digsX->force = force_To_DigsX_From_TenXY_Entry;
+ tenXY->strm = (Real) digsX;
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToOnlyChild(digsX, r);
+ drawEqEdge(tenXY, tenXY->strm);
+ endGraphUpdate();
+#endif
+ }
+ }
+}
+
+void
+force_To_TenXY_X_From_SignX_Entry()
+{
+ TenXY *tenXY;
+ SignX *signX;
+ void force_To_TenXY_X_From_SignX_Cont();
+
+ tenXY = (TenXY *) POP;
+ signX = (SignX *) tenXY->x;
+
+ PUSH_2(force_To_TenXY_X_From_SignX_Cont, tenXY);
+ if (signX->tag.value == SIGN_UNKN)
+ PUSH_2(signX->force, signX);
+}
+
+void
+force_To_TenXY_X_From_SignX_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+ absorbSignIntoTenXY_X(tenXY);
+}
+
+void
+force_To_TenXY_Y_From_SignX_Entry()
+{
+ TenXY *tenXY;
+ SignX *signX;
+ void force_To_TenXY_Y_From_SignX_Cont();
+
+ tenXY = (TenXY *) POP;
+ signX = (SignX *) tenXY->y;
+
+ PUSH_2(force_To_TenXY_Y_From_SignX_Cont, tenXY);
+ if (signX->tag.value == SIGN_UNKN)
+ PUSH_2(signX->force, signX);
+}
+
+void
+force_To_TenXY_Y_From_SignX_Cont()
+{
+ TenXY *tenXY;
+
+ tenXY = (TenXY *) POP;
+ absorbSignIntoTenXY_Y(tenXY);
+}
+
+/*
+ * This handles the case when the x arg of a signed TenXY is a MatX.
+ * This version is strict. It inspects its argument first. If it too is
+ * signed, then it forces it before reducing the two matrices to one.
+ */
+void
+force_To_TenXY_X_From_MatX_Signed_Entry()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ void force_To_TenXY_X_From_MatX_Signed_Cont();
+ void force_To_TenXY_X_From_Vec_Signed();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->x->gen.tag.type == VECTOR) {
+ PUSH_2(force_To_TenXY_X_From_Vec_Signed, tenXY);
+ return;
+ }
+
+ matX = (MatX *) tenXY->x;
+
+ PUSH_2(force_To_TenXY_X_From_MatX_Signed_Cont, tenXY);
+ if (matX->x->gen.tag.isSigned)
+ PUSH_2(matX->force, matX);
+}
+
+/*
+ * The following code is exactly the same as the unsigned case except there
+ * are fewer things on the stack. The two can probably be reconciled
+ * as the number of digits is irrelevant when reducing matrices. We leave
+ * them separate in case one or other can be improved at a later time.
+ */
+void
+force_To_TenXY_X_From_MatX_Signed_Cont()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_X_From_Vec_Signed();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->x->gen.tag.type == VECTOR) {
+ PUSH_2(force_To_TenXY_X_From_Vec_Signed, tenXY);
+ return;
+ }
+
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[2], tenXY->x->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[1], tenXY->ten[3], tenXY->x->matX.mat);
+ normalizeTensor(tenXY->ten);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->matX.x);
+ endGraphUpdate();
+#endif
+
+ tenXY->x = tenXY->x->matX.x;
+ setTenXY_X_MethodUnsigned(tenXY);
+}
+
+void
+force_To_TenXY_X_From_Vec_Signed()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ mpz_t a, b, c, d; /* temporary storage while we clobber the TenXY */
+ Real strm; /* temporary storage again */
+ int totalEmitted;
+
+ tenXY = (TenXY *) POP;
+
+ multVectorPairTimesVector(tenXY->ten[0], tenXY->ten[2], tenXY->x->vec.vec);
+ multVectorPairTimesVector(tenXY->ten[1], tenXY->ten[3], tenXY->x->vec.vec);
+
+ a[0] = tenXY->ten[0][0][0];
+ b[0] = tenXY->ten[0][1][0];
+ c[0] = tenXY->ten[1][0][0];
+ d[0] = tenXY->ten[1][1][0];
+ strm = tenXY->strm;
+ totalEmitted = tenXY->totalEmitted;
+
+ mpz_clear(tenXY->ten[2][0]);
+ mpz_clear(tenXY->ten[2][1]);
+ mpz_clear(tenXY->ten[3][0]);
+ mpz_clear(tenXY->ten[3][1]);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ endGraphUpdate();
+#endif
+
+ matX = (MatX *) tenXY;
+ matX->tag.type = MATX;
+ matX->x = tenXY->y;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToOnlyChild(matX, matX->x);
+ endGraphUpdate();
+
+#endif
+ matX->mat[0][0][0] = a[0];
+ matX->mat[0][1][0] = b[0];
+ matX->mat[1][0][0] = c[0];
+ matX->mat[1][1][0] = d[0];
+ normalizeMatrix(matX->mat);
+ matX->strm = strm;
+ matX->totalEmitted = totalEmitted;
+
+/*
+ setMatXMethodUnsigned(matX);
+*/
+ if (matX->x->gen.tag.isSigned)
+ setMatXMethodSigned(matX);
+ else
+ setMatXMethodUnsigned(matX);
+}
+
+void
+force_To_TenXY_X_From_TenXY_Signed_Entry()
+{
+ TenXY *tenXY, *arg;
+ void force_To_TenXY_X_From_MatX_Signed_Entry();
+ void force_To_TenXY_X_From_TenXY_Signed_Cont();
+ void force_To_TenXY_X_From_TenXY_Signed_Cont_X();
+
+ tenXY = (TenXY *) POP;
+ arg = (TenXY *) tenXY->x;
+
+ if (arg->tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_X_From_MatX_Signed_Entry, tenXY);
+ return;
+ }
+
+ if (arg->x->gen.tag.isSigned) {
+ if (arg->y->gen.tag.isSigned) {
+ PUSH_2(force_To_TenXY_X_From_TenXY_Signed_Cont_X, tenXY);
+ PUSH_2(arg->forceY, arg);
+ }
+ else {
+ PUSH_2(force_To_TenXY_X_From_TenXY_Signed_Cont, tenXY);
+ PUSH_2(arg->forceX, arg);
+ }
+ }
+ else {
+ if (arg->y->gen.tag.isSigned) {
+ PUSH_2(force_To_TenXY_X_From_TenXY_Signed_Cont, tenXY);
+ PUSH_2(arg->forceY, arg);
+ }
+ else
+ PUSH_2(force_To_TenXY_X_From_TenXY_Signed_Cont, tenXY);
+ }
+}
+
+void
+force_To_TenXY_X_From_TenXY_Signed_Cont_X()
+{
+ TenXY *tenXY, *arg;
+ void force_To_TenXY_X_From_TenXY_Signed_Cont();
+ void force_To_TenXY_X_From_MatX_Signed_Entry();
+
+ tenXY = (TenXY *) POP;
+ arg = (TenXY *) tenXY->x;
+
+ if (arg->tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_X_From_MatX_Signed_Entry, tenXY);
+ return;
+ }
+
+ PUSH_2(force_To_TenXY_X_From_TenXY_Signed_Cont, tenXY);
+
+ if (arg->x->gen.tag.isSigned)
+ PUSH_2(arg->forceX, arg);
+}
+
+void
+force_To_TenXY_X_From_TenXY_Signed_Cont()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_X_From_MatX_Signed_Cont();
+ void force_To_TenXY_X_From_SignX_Entry();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->x->gen.tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_X_From_MatX_Signed_Cont, tenXY);
+ return;
+ }
+
+ createSignedStreamForTenXY((TenXY *) tenXY->x);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ newEdgeToXChild(tenXY, tenXY->x->tenXY.strm);
+ endGraphUpdate();
+#endif
+
+ tenXY->x = tenXY->x->tenXY.strm;
+ tenXY->forceX = force_To_TenXY_X_From_SignX_Entry;
+ PUSH_2(tenXY->forceX, tenXY);
+}
+
+/*
+ * This handles the case when the x arg of a signed TenXY is a MatX.
+ * This version is strict. It inspects its argument first. If it too is
+ * signed, then it forces it before reducing the two matrices to one.
+ */
+void
+force_To_TenXY_Y_From_MatX_Signed_Entry()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ void force_To_TenXY_Y_From_MatX_Signed_Cont();
+ void force_To_TenXY_Y_From_Vec_Signed();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->y->gen.tag.type == VECTOR) {
+ PUSH_2(force_To_TenXY_Y_From_Vec_Signed, tenXY);
+ return;
+ }
+
+ matX = (MatX *) tenXY->y;
+
+ PUSH_2(force_To_TenXY_Y_From_MatX_Signed_Cont, tenXY);
+ if (matX->x->gen.tag.isSigned)
+ PUSH_2(matX->force, matX);
+}
+
+/*
+ * The following code is exactly the same as the unsigned case except there
+ * are fewer things on the stack. The two can probably be reconciled
+ * as the number of digits is irrelevant when reducing matrices. We leave
+ * them separate in case one or other can be improved at a later time.
+ */
+void
+force_To_TenXY_Y_From_MatX_Signed_Cont()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_Y_From_Vec_Signed();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->y->gen.tag.type == VECTOR) {
+ PUSH_2(force_To_TenXY_Y_From_Vec_Signed, tenXY);
+ return;
+ }
+
+ multVectorPairTimesMatrix(tenXY->ten[0], tenXY->ten[1], tenXY->y->matX.mat);
+ multVectorPairTimesMatrix(tenXY->ten[2], tenXY->ten[3], tenXY->y->matX.mat);
+ normalizeTensor(tenXY->ten);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->matX.x);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->matX.x;
+ setTenXY_Y_MethodUnsigned(tenXY);
+}
+
+void
+force_To_TenXY_Y_From_Vec_Signed()
+{
+ TenXY *tenXY;
+ MatX *matX;
+ mpz_t a, b, c, d; /* temporary storage while we clobber the TenXY */
+ Real strm; /* temporary storage again */
+ int totalEmitted;
+
+ tenXY = (TenXY *) POP;
+
+ multVectorPairTimesVector(tenXY->ten[0], tenXY->ten[1], tenXY->y->vec.vec);
+ multVectorPairTimesVector(tenXY->ten[2], tenXY->ten[3], tenXY->y->vec.vec);
+
+ a[0] = tenXY->ten[0][0][0];
+ b[0] = tenXY->ten[0][1][0];
+ c[0] = tenXY->ten[2][0][0];
+ d[0] = tenXY->ten[2][1][0];
+ strm = tenXY->strm;
+ totalEmitted = tenXY->totalEmitted;
+
+ mpz_clear(tenXY->ten[1][0]);
+ mpz_clear(tenXY->ten[1][1]);
+ mpz_clear(tenXY->ten[3][0]);
+ mpz_clear(tenXY->ten[3][1]);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToXChild(tenXY, tenXY->x);
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ endGraphUpdate();
+#endif
+
+ matX = (MatX *) tenXY;
+ matX->tag.type = MATX;
+ matX->x = tenXY->x;
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ newEdgeToOnlyChild(matX, matX->x);
+ endGraphUpdate();
+
+#endif
+ matX->mat[0][0][0] = a[0];
+ matX->mat[0][1][0] = b[0];
+ matX->mat[1][0][0] = c[0];
+ matX->mat[1][1][0] = d[0];
+ normalizeMatrix(matX->mat);
+ matX->strm = strm;
+ matX->totalEmitted = totalEmitted;
+
+/*
+ setMatXMethodUnsigned(matX);
+*/
+ if (matX->x->gen.tag.isSigned)
+ setMatXMethodSigned(matX);
+ else
+ setMatXMethodUnsigned(matX);
+}
+
+void
+force_To_TenXY_Y_From_TenXY_Signed_Entry()
+{
+ TenXY *tenXY, *arg;
+ void force_To_TenXY_Y_From_MatX_Signed_Entry();
+ void force_To_TenXY_Y_From_TenXY_Signed_Cont();
+ void force_To_TenXY_Y_From_TenXY_Signed_Cont_X();
+
+ tenXY = (TenXY *) POP;
+ arg = (TenXY *) tenXY->y;
+
+ if (arg->tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_Y_From_MatX_Signed_Entry, tenXY);
+ return;
+ }
+
+ if (arg->x->gen.tag.isSigned) {
+ if (arg->y->gen.tag.isSigned) {
+ PUSH_2(force_To_TenXY_Y_From_TenXY_Signed_Cont_X, tenXY);
+ PUSH_2(arg->forceY, arg);
+ }
+ else {
+ PUSH_2(force_To_TenXY_Y_From_TenXY_Signed_Cont, tenXY);
+ PUSH_2(arg->forceX, arg);
+ }
+ }
+ else {
+ if (arg->y->gen.tag.isSigned) {
+ PUSH_2(force_To_TenXY_Y_From_TenXY_Signed_Cont, tenXY);
+ PUSH_2(arg->forceY, arg);
+ }
+ else
+ PUSH_2(force_To_TenXY_Y_From_TenXY_Signed_Cont, tenXY);
+ }
+}
+
+void
+force_To_TenXY_Y_From_TenXY_Signed_Cont_X()
+{
+ TenXY *tenXY, *arg;
+ void force_To_TenXY_Y_From_TenXY_Signed_Cont();
+ void force_To_TenXY_Y_From_MatX_Signed_Entry();
+
+ tenXY = (TenXY *) POP;
+ arg = (TenXY *) tenXY->y;
+
+ if (arg->tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_Y_From_MatX_Signed_Entry, tenXY);
+ return;
+ }
+
+ PUSH_2(force_To_TenXY_Y_From_TenXY_Signed_Cont, tenXY);
+
+ if (arg->x->gen.tag.isSigned)
+ PUSH_2(arg->forceX, arg);
+}
+
+void
+force_To_TenXY_Y_From_TenXY_Signed_Cont()
+{
+ TenXY *tenXY;
+ void force_To_TenXY_Y_From_MatX_Signed_Cont();
+ void force_To_TenXY_Y_From_SignX_Entry();
+
+ tenXY = (TenXY *) POP;
+
+ if (tenXY->y->gen.tag.type != TENXY) {
+ PUSH_2(force_To_TenXY_Y_From_MatX_Signed_Cont, tenXY);
+ return;
+ }
+
+ createSignedStreamForTenXY((TenXY *) tenXY->y);
+
+#ifdef DAVINCI
+ beginGraphUpdate();
+ deleteEdgeToYChild(tenXY, tenXY->y);
+ newEdgeToYChild(tenXY, tenXY->y->tenXY.strm);
+ endGraphUpdate();
+#endif
+
+ tenXY->y = tenXY->y->tenXY.strm;
+ tenXY->forceY = force_To_TenXY_Y_From_SignX_Entry;
+ PUSH_2(tenXY->forceY, tenXY);
+}
+
+void
+setTenXY_X_MethodUnsigned(TenXY *tenXY)
+{
+ void force_To_TenXY_X_From_SignX_Entry();
+ void force_To_TenXY_X_From_DigsX_Entry();
+ void force_To_TenXY_X_From_Vec();
+ void force_To_TenXY_X_From_MatX();
+ void force_To_TenXY_X_From_TenXY();
+ void force_To_TenXY_X_From_Alt_Entry();
+ void force_To_TenXY_X_From_Cls_Entry();
+
+ switch (tenXY->x->gen.tag.type) {
+ case SIGNX :
+ Error(FATAL, E_INT, "setTenXY_X_MethodUnsigned", "x is signed");
+ break;
+ case DIGSX :
+ tenXY->forceX = force_To_TenXY_X_From_DigsX_Entry;
+ break;
+ case ALT :
+ tenXY->forceX = force_To_TenXY_X_From_Alt_Entry;
+ break;
+ case VECTOR :
+ tenXY->forceX = force_To_TenXY_X_From_Vec;
+ break;
+ case MATX :
+ tenXY->forceX = force_To_TenXY_X_From_MatX;
+ break;
+ case TENXY :
+ tenXY->forceX = force_To_TenXY_X_From_TenXY;
+ break;
+ case CLOSURE :
+ tenXY->forceX = force_To_TenXY_X_From_Cls_Entry;
+ break;
+ default :
+ Error(FATAL, E_INT, "setTenXY_X_MethodUnsigned",
+ "something wrong with x");
+ break;
+ }
+}
+
+void
+setTenXY_Y_MethodUnsigned(TenXY *tenXY)
+{
+ void force_To_TenXY_Y_From_SignX_Entry();
+ void force_To_TenXY_Y_From_DigsX_Entry();
+ void force_To_TenXY_Y_From_Vec();
+ void force_To_TenXY_Y_From_MatX();
+ void force_To_TenXY_Y_From_TenXY();
+ void force_To_TenXY_Y_From_Alt_Entry();
+ void force_To_TenXY_Y_From_Cls_Entry();
+
+ switch (tenXY->y->gen.tag.type) {
+ case SIGNX :
+ Error(FATAL, E_INT, "setTenXY_Y_MethodUnsigned", "y is signed");
+ break;
+ case DIGSX :
+ tenXY->forceY = force_To_TenXY_Y_From_DigsX_Entry;
+ break;
+ case ALT :
+ tenXY->forceY = force_To_TenXY_Y_From_Alt_Entry;
+ break;
+ case VECTOR :
+ tenXY->forceY = force_To_TenXY_Y_From_Vec;
+ break;
+ case MATX :
+ tenXY->forceY = force_To_TenXY_Y_From_MatX;
+ break;
+ case TENXY :
+ tenXY->forceY = force_To_TenXY_Y_From_TenXY;
+ break;
+ case CLOSURE :
+ tenXY->forceY = force_To_TenXY_Y_From_Cls_Entry;
+ break;
+ default :
+ Error(FATAL, E_INT, "setTenXY_Y_MethodUnsigned",
+ "something wrong with y");
+ break;
+ }
+}
+
+void
+setTenXY_X_MethodSigned(TenXY *tenXY)
+{
+ void force_To_TenXY_X_From_SignX_Entry();
+ void force_To_TenXY_X_From_DigsX_Signed();
+ void force_To_TenXY_X_From_Vec_Signed();
+ void force_To_TenXY_X_From_MatX_Signed_Entry();
+ void force_To_TenXY_X_From_TenXY_Signed_Entry();
+ void force_To_TenXY_X_From_Alt_Signed_Entry();
+ void force_To_TenXY_X_From_Cls_Signed_Entry();
+
+ switch (tenXY->x->gen.tag.type) {
+ case SIGNX :
+ tenXY->forceX = force_To_TenXY_X_From_SignX_Entry;
+ break;
+ case DIGSX :
+ tenXY->forceX = force_To_TenXY_X_From_DigsX_Signed;
+ break;
+ case ALT :
+ tenXY->forceX = force_To_TenXY_X_From_Alt_Signed_Entry;
+ break;
+ case VECTOR :
+ tenXY->forceX = force_To_TenXY_X_From_Vec_Signed;
+ break;
+ case MATX :
+ tenXY->forceX = force_To_TenXY_X_From_MatX_Signed_Entry;
+ break;
+ case TENXY :
+ tenXY->forceX = force_To_TenXY_X_From_TenXY_Signed_Entry;
+ break;
+ case CLOSURE :
+ tenXY->forceX = force_To_TenXY_X_From_Cls_Signed_Entry;
+ break;
+ default :
+ Error(FATAL, E_INT, "setTenXY_X_MethodSigned",
+ "something wrong with x");
+ break;
+ }
+}
+
+void
+setTenXY_Y_MethodSigned(TenXY *tenXY)
+{
+ void force_To_TenXY_Y_From_SignX_Entry();
+ void force_To_TenXY_Y_From_DigsX_Signed();
+ void force_To_TenXY_Y_From_Vec_Signed();
+ void force_To_TenXY_Y_From_MatX_Signed_Entry();
+ void force_To_TenXY_Y_From_TenXY_Signed_Entry();
+ void force_To_TenXY_Y_From_Alt_Signed_Entry();
+ void force_To_TenXY_Y_From_Cls_Signed_Entry();
+
+ switch (tenXY->y->gen.tag.type) {
+ case SIGNX :
+ tenXY->forceY = force_To_TenXY_Y_From_SignX_Entry;
+ break;
+ case DIGSX :
+ tenXY->forceY = force_To_TenXY_Y_From_DigsX_Signed;
+ break;
+ case ALT :
+ tenXY->forceY = force_To_TenXY_Y_From_Alt_Signed_Entry;
+ break;
+ case VECTOR :
+ tenXY->forceY = force_To_TenXY_Y_From_Vec_Signed;
+ break;
+ case MATX :
+ tenXY->forceY = force_To_TenXY_Y_From_MatX_Signed_Entry;
+ break;
+ case TENXY :
+ tenXY->forceY = force_To_TenXY_Y_From_TenXY_Signed_Entry;
+ break;
+ case CLOSURE :
+ tenXY->forceY = force_To_TenXY_Y_From_Cls_Signed_Entry;
+ break;
+ default :
+ Error(FATAL, E_INT, "setTenXY_Y_MethodSigned",
+ "something wrong with y");
+ break;
+ }
+}