From 11da511c784eca003deb90c23570f0873954e0de Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Sat, 18 Nov 2023 06:11:09 -0600 Subject: Initial commit. --- ic-reals-6.3/base/MatX.c | 902 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 902 insertions(+) create mode 100644 ic-reals-6.3/base/MatX.c (limited to 'ic-reals-6.3/base/MatX.c') diff --git a/ic-reals-6.3/base/MatX.c b/ic-reals-6.3/base/MatX.c new file mode 100644 index 0000000..87cdcd6 --- /dev/null +++ b/ic-reals-6.3/base/MatX.c @@ -0,0 +1,902 @@ +/* + * 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 +#include "real.h" +#include "real-impl.h" + +/* + * Functions for allocating and manipulating matrix LFTs in the heap. + */ + +void setMatXMethodSigned(MatX *); +void setMatXMethodUnsigned(MatX *); +void absorbDigsXIntoMatX(MatX *); + +MatX * +allocMatX() +{ + MatX *matX; + + if ((matX = (MatX *) malloc (sizeof(MatX))) == NULL) + Error(FATAL, E_INT, "allocMatX", "malloc failed"); + +#ifdef DAVINCI + newNodeId(matX); +#else +#ifdef TRACE + newNodeId(matX); +#endif +#endif + + matX->tag.type = MATX; + matX->tag.dumped = FALSE; + matX->strm = (Real) NULL; + +#ifdef DAVINCI + beginGraphUpdate(); + newNode(matX, MATX); + endGraphUpdate(); +#endif + + + return matX; +} + +/* + * Allocates and fills a matrix object in the heap. Included below + * is code for eagerly reducing a matrix against its argument. Eager + * reduction reduces the amount of garbage in the heap. At this point, + * eager reduction is disabled as some functions which call this expect + * to get back a MatX object. With reduction they might get either + * a MatX or a Vec. + */ +Real +matrix_Int(Real x, int a, int b, int c, int d) +{ + MatX *matX; + +#ifdef LATER + /* + * If the argument is a vector, then we eagerly reduce our given + * matrix to a vector. We do this in tmp storage to avoid creating + * garbage in the heap. + */ + if (x->gen.tag.type == VECTOR) { + mpz_set_si(bigTmpMat[0][0], a); + mpz_set_si(bigTmpMat[0][1], b); + mpz_set_si(bigTmpMat[1][0], c); + mpz_set_si(bigTmpMat[1][1], d); + multVectorPairTimesVector(bigTmpMat[0], bigTmpMat[1], x->vec.vec); + return vector_Z(bigTmpMat[0][0], bigTmpMat[0][1]); + } +#endif + + /* + * So now we know we will end up with matrix, so we allocate one. + */ + matX = allocMatX(); + + mpz_init_set_si(matX->mat[0][0], a); + mpz_init_set_si(matX->mat[0][1], b); + mpz_init_set_si(matX->mat[1][0], c); + mpz_init_set_si(matX->mat[1][1], d); + + /* + * ### should perhaps check that there are no zero columns + */ + + /* remove powers of 2 from the matrix */ + normalizeMatrix(matX->mat); + + /* make the matrix positive if it is negative (ie no entries > 0) */ + if (matrixSign(matX->mat) < 0) + negateMatrix(matX->mat); + + matX->x = (Real) x; + +#ifdef DAVINCI + beginGraphUpdate(); + newEdgeToOnlyChild(matX, x); + endGraphUpdate(); +#endif + +#ifdef LATER + /* + * Now we eagerly consume any matrix which follows. This may be unwise. + */ + if (x->gen.tag.type == MATX) { + multVectorPairTimesMatrix(matX->mat[0], matX->mat[1], x->matX.mat); +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, x->matX.x); + endGraphUpdate(); +#endif + matX->x = x->matX.x; + } +#endif + + /* + * A MatX is signed if the there are entries in the matrix of different + * signs or if the argument to the MatX is signed. + */ + if (matX->x->gen.tag.isSigned || matrixSign(matX->mat) == 0) + matX->tag.isSigned = TRUE; + + if (matX->x->gen.tag.isSigned) + setMatXMethodSigned(matX); + else + setMatXMethodUnsigned(matX); + return (Real) matX; +} + +/* + * This is exactly as above but in this case the matrix is filled with + * large (GMP) integers rather than machine integers. + */ +Real +matrix_Z(Real x, mpz_t a, mpz_t b, mpz_t c, mpz_t d) +{ + MatX *matX; + +#ifdef LATER + /* + * If the argument is a vector, then we eagerly reduce our given + * matrix to a vector. We do this in tmp storage to avoid creating + * garbage in the heap. + */ + if (x->gen.tag.type == VECTOR) { + mpz_set(bigTmpMat[0][0], a); + mpz_set(bigTmpMat[0][1], b); + mpz_set(bigTmpMat[1][0], c); + mpz_set(bigTmpMat[1][1], d); + multVectorPairTimesVector(bigTmpMat[0], bigTmpMat[1], x->vec.vec); + return vector_Z(bigTmpMat[0][0], bigTmpMat[0][1]); + } +#endif + + /* + * So now we know we will end up with a matrix, so we allocate one. + */ + matX = allocMatX(); + + mpz_init_set(matX->mat[0][0], a); + mpz_init_set(matX->mat[0][1], b); + mpz_init_set(matX->mat[1][0], c); + mpz_init_set(matX->mat[1][1], d); + + /* + * ### should perhaps check that there are no zero columns + */ + + /* remove powers of 2 from the matrix */ + normalizeMatrix(matX->mat); + + /* make the matrix positive if it is negative (ie no entries > 0) */ + if (matrixSign(matX->mat) < 0) + negateMatrix(matX->mat); + + matX->x = (Real) x; + +#ifdef DAVINCI + beginGraphUpdate(); + newEdgeToOnlyChild(matX, x); + endGraphUpdate(); +#endif + +#ifdef LATER + /* + * Now we eagerly consume any matrix which follows. This may be unwise. + */ + if (x->gen.tag.type == MATX) { + multVectorPairTimesMatrix(matX->mat[0], matX->mat[1], x->matX.mat); +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, x->matX.x); + endGraphUpdate(); +#endif + matX->x = x->matX.x; + } +#endif + + /* + * A MatX is signed if the there are entries in the matrix of different + * signs or if the argument to the MatX is signed. + */ + if (matX->x->gen.tag.isSigned || matrixSign(matX->mat) == 0) + matX->tag.isSigned = TRUE; + + if (matX->x->gen.tag.isSigned) + setMatXMethodSigned(matX); + else + setMatXMethodUnsigned(matX); + return (Real) matX; +} + +void +force_To_MatX_From_DigsX_Entry() +{ + MatX *matX; + DigsX *digsX; + int digitsNeeded; + void force_To_MatX_From_DigsX_Cont(); + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + digsX = (DigsX *) matX->x; + + PUSH_3(force_To_MatX_From_DigsX_Cont, matX, 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_MatX_From_DigsX_Cont() +{ + MatX *matX; + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + + absorbDigsXIntoMatX(matX); +} + +/* + * It can happen that, for example, an Alt is deemed signed, and yet + * the value it ultimately yields is unsigned. In this case we need to + * emit a sign from a DigsZ. This is little more than a no-op. + */ +void +force_To_MatX_From_DigsX_Signed() +{ + MatX *matX; + void force_To_MatX_From_DigsX_Entry(); + + matX = (MatX *) POP; + matX->force = force_To_MatX_From_DigsX_Entry; +} + +/* + * When a matrix is applied to an vector, the matrix reduces to a vector. + * The reduction happens in place. That is, we overwrite the matrix + * with a vector. That way any other consumers which share the matrix + * (now vector), end up pointing to the vector. + */ +void +force_To_MatX_From_Vec() +{ + MatX *matX; + Vec *vec; + mpz_t a, b; /* temporary storage while we clobber the MatX */ + Real strm; /* temporary storage while we clobber the MatX */ + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + + multVectorPairTimesVector(matX->mat[0], matX->mat[1], matX->x->vec.vec); + + a[0] = matX->mat[0][0][0]; + b[0] = matX->mat[0][1][0]; + strm = matX->strm; + + mpz_clear(matX->mat[1][0]); + mpz_clear(matX->mat[1][1]); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + endGraphUpdate(); +#endif + + vec = (Vec *) matX; + + vec->tag.type = VECTOR; + vec->vec[0][0] = a[0]; + vec->vec[1][0] = b[0]; + normalizeVector(vec->vec); + vec->strm = strm; +} + +/* + * Same as the above, except for the signed case. The stack frame + * is different. + */ +void +force_To_MatX_From_Vec_Signed() +{ + MatX *matX; + Vec *vec; + mpz_t a, b; /* temporary storage while we clobber the MatX */ + Real strm; /* temporary storage while we clobber the MatX */ + + matX = (MatX *) POP; + + multVectorPairTimesVector(matX->mat[0], matX->mat[1], matX->x->vec.vec); + + a[0] = matX->mat[0][0][0]; + b[0] = matX->mat[0][1][0]; + strm = matX->strm; + + mpz_clear(matX->mat[1][0]); + mpz_clear(matX->mat[1][1]); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + endGraphUpdate(); +#endif + + vec = (Vec *) matX; + + vec->tag.type = VECTOR; + vec->vec[0][0] = a[0]; + vec->vec[1][0] = b[0]; + normalizeVector(vec->vec); + vec->tag.isSigned = TRUE; + vec->strm = strm; +} + +void +force_To_MatX_From_MatX() +{ + MatX *matX; + int digitsNeeded; + void force_To_MatX_From_Vec(); + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + + if (matX->x->gen.tag.type == VECTOR) { + PUSH_3(force_To_MatX_From_Vec, matX, digitsNeeded); + return; + } + + multVectorPairTimesMatrix(matX->mat[0], matX->mat[1], matX->x->matX.mat); + normalizeMatrix(matX->mat); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, matX->x->matX.x); + endGraphUpdate(); +#endif + matX->x = matX->x->matX.x; + setMatXMethodUnsigned(matX); +} + +/* + * This handles the case when the arg of a signed MatX is another 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_MatX_From_MatX_Signed_Entry() +{ + MatX *matX, *arg; + void force_To_MatX_From_MatX_Signed_Cont(); + void force_To_MatX_From_Vec_Signed(); + + matX = (MatX *) POP; + + if (matX->x->gen.tag.type == VECTOR) { + PUSH_2(force_To_MatX_From_Vec_Signed, matX); + return; + } + + arg = (MatX *) matX->x; + + PUSH_2(force_To_MatX_From_MatX_Signed_Cont, matX); + if (arg->x->gen.tag.isSigned) + PUSH_2(arg->force, arg); +} + +/* + * 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_MatX_From_MatX_Signed_Cont() +{ + MatX *matX; + void force_To_MatX_From_Vec_Signed(); + + matX = (MatX *) POP; + + if (matX->x->gen.tag.type == VECTOR) { + PUSH_2(force_To_MatX_From_Vec_Signed, matX); + return; + } + + multVectorPairTimesMatrix(matX->mat[0], matX->mat[1], matX->x->matX.mat); + normalizeMatrix(matX->mat); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, matX->x->matX.x); + endGraphUpdate(); +#endif + + matX->x = matX->x->matX.x; + setMatXMethodUnsigned(matX); +} + +void +force_To_MatX_From_TenXY() +{ + MatX *matX; + int digitsNeeded; + void force_To_MatX_From_MatX(); + void force_To_MatX_From_DigsX_Entry(); + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + + if (matX->x->gen.tag.type != TENXY) { + PUSH_3(force_To_MatX_From_MatX, matX, digitsNeeded); + return; + } + + createUnsignedStreamForTenXY(&matX->x->tenXY); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, matX->x->tenXY.strm); + endGraphUpdate(); +#endif + + matX->x = matX->x->tenXY.strm; + matX->force = force_To_MatX_From_DigsX_Entry; + PUSH_3(matX->force, matX, digitsNeeded); +} + +void +force_To_MatX_From_TenXY_Signed_Entry() +{ + MatX *matX; + TenXY *tenXY; + void force_To_MatX_From_MatX_Signed_Entry(); + void force_To_MatX_From_TenXY_Signed_Cont(); + void force_To_MatX_From_TenXY_Signed_Cont_X(); + + matX = (MatX *) POP; + tenXY = (TenXY *) matX->x; + + if (matX->x->gen.tag.type != TENXY) { + PUSH_2(force_To_MatX_From_MatX_Signed_Entry, matX); + return; + } + + if (tenXY->x->gen.tag.isSigned) { + if (tenXY->y->gen.tag.isSigned) { + PUSH_2(force_To_MatX_From_TenXY_Signed_Cont_X, matX); + PUSH_2(tenXY->forceY, tenXY); + } + else { + PUSH_2(force_To_MatX_From_TenXY_Signed_Cont, matX); + PUSH_2(tenXY->forceX, tenXY); + } + } + else { + if (tenXY->y->gen.tag.isSigned) { + PUSH_2(force_To_MatX_From_TenXY_Signed_Cont, matX); + PUSH_2(tenXY->forceY, tenXY); + } + else + PUSH_2(force_To_MatX_From_TenXY_Signed_Cont, matX); + } +} + +/* + * Here we have already forced the y argument, and now we force the sign + * from the x side of the tensor. + */ +void +force_To_MatX_From_TenXY_Signed_Cont_X() +{ + MatX *matX; + TenXY *tenXY; + void force_To_MatX_From_MatX_Signed_Entry(); + void force_To_MatX_From_TenXY_Signed_Cont(); + + matX = (MatX *) POP; + tenXY = (TenXY *) matX->x; + + if (matX->x->gen.tag.type != TENXY) { + PUSH_2(force_To_MatX_From_MatX_Signed_Entry, matX); + return; + } + + PUSH_2(force_To_MatX_From_TenXY_Signed_Cont, matX); + if (tenXY->x->gen.tag.isSigned) + PUSH_2(tenXY->forceX, tenXY); +} + +void +force_To_MatX_From_TenXY_Signed_Cont() +{ + MatX *matX; + void force_To_MatX_From_MatX_Signed_Cont(); + void force_To_MatX_From_SignX_Entry(); + + matX = (MatX *) POP; + + if (matX->x->gen.tag.type != TENXY) { + PUSH_2(force_To_MatX_From_MatX_Signed_Cont, matX); + return; + } + + createSignedStreamForTenXY(&matX->x->tenXY); + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, matX->x->tenXY.strm); + endGraphUpdate(); +#endif + + matX->x = matX->x->tenXY.strm; + matX->force = force_To_MatX_From_SignX_Entry; + PUSH_2(matX->force, matX); +} + +void +force_To_MatX_From_Alt_Entry() +{ + MatX *matX; + Alt *alt; + void force_To_Alt_Entry(); + void force_To_MatX_From_Alt_Cont(); + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + alt = (Alt *) matX->x; + + PUSH_3(force_To_MatX_From_Alt_Cont, matX, 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 (alt->redirect == NULL) + PUSH_2(force_To_Alt_Entry, alt); +} + +void +force_To_MatX_From_Alt_Cont() +{ + MatX *matX; + Alt *alt; + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + alt = (Alt *) matX->x; + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, alt); + newEdgeToOnlyChild(matX, alt->redirect); + endGraphUpdate(); +#endif + matX->x = alt->redirect; + setMatXMethodUnsigned(matX); + + PUSH_3(matX->force, matX, digitsNeeded); +} + +void +force_To_MatX_From_Cls_Entry() +{ + MatX *matX; + Cls *cls; + void force_To_MatX_From_Cls_Cont(); + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + cls = (Cls *) matX->x; + + PUSH_3(force_To_MatX_From_Cls_Cont, matX, 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 (cls->redirect == NULL) + PUSH_2(cls->force, cls); +} + +void +force_To_MatX_From_Cls_Cont() +{ + MatX *matX; + Cls *cls; + int digitsNeeded; + + matX = (MatX *) POP; + digitsNeeded = (int) POP; + cls = (Cls *) matX->x; + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, cls); + newEdgeToOnlyChild(matX, cls->redirect); + endGraphUpdate(); +#endif + matX->x = cls->redirect; + setMatXMethodUnsigned(matX); + + PUSH_3(matX->force, matX, digitsNeeded); +} + +void +force_To_MatX_From_Alt_Signed_Entry() +{ + MatX *matX; + Alt *alt; + void force_To_Alt_Entry(); + void force_To_MatX_From_Alt_Signed_Cont(); + + matX = (MatX *) POP; + alt = (Alt *) matX->x; + + PUSH_2(force_To_MatX_From_Alt_Signed_Cont, matX); + + /* + * 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 (alt->redirect == NULL) + PUSH_2(force_To_Alt_Entry, alt); +} + +void +force_To_MatX_From_Alt_Signed_Cont() +{ + MatX *matX; + Alt *alt; + + matX = (MatX *) POP; + alt = (Alt *) matX->x; + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, alt); + newEdgeToOnlyChild(matX, alt->redirect); + endGraphUpdate(); +#endif + + matX->x = alt->redirect; + setMatXMethodSigned(matX); + + PUSH_2(matX->force, matX); +} + +void +force_To_MatX_From_Cls_Signed_Entry() +{ + MatX *matX; + Cls *cls; + void force_To_MatX_From_Cls_Signed_Cont(); + + matX = (MatX *) POP; + cls = (Cls *) matX->x; + + PUSH_2(force_To_MatX_From_Cls_Signed_Cont, matX); + + /* + * 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 (cls->redirect == NULL) + PUSH_2(cls->force, cls); +} + +void +force_To_MatX_From_Cls_Signed_Cont() +{ + MatX *matX; + Cls *cls; + + matX = (MatX *) POP; + cls = (Cls *) matX->x; + +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, cls); + newEdgeToOnlyChild(matX, cls->redirect); + endGraphUpdate(); +#endif + + matX->x = cls->redirect; + setMatXMethodSigned(matX); + + PUSH_2(matX->force, matX); +} + +void +force_To_MatX_From_SignX_Entry() +{ + MatX *matX; + SignX *signX; + void force_To_MatX_From_SignX_Cont(); + + matX = (MatX *) POP; + signX = (SignX *) matX->x; + + PUSH_2(force_To_MatX_From_SignX_Cont, matX); + if (signX->tag.value == SIGN_UNKN) + PUSH_2(signX->force, signX); +} + +void +force_To_MatX_From_SignX_Cont() +{ + MatX *matX; + void absorbSignIntoMatX(MatX *); + + matX = (MatX *) POP; + absorbSignIntoMatX(matX); +} + +void +absorbSignIntoMatX(MatX *matX) +{ + absorbSignIntoVectorPair(matX->mat[0], matX->mat[1], + matX->x->signX.tag.value); +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, matX->x); + newEdgeToOnlyChild(matX, matX->x->signX.x); + endGraphUpdate(); +#endif + matX->x = matX->x->signX.x; + setMatXMethodUnsigned(matX); +} + +void +setMatXMethodSigned(MatX *matX) +{ + void force_To_MatX_From_SignX_Entry(); + void force_To_MatX_From_DigsX_Signed(); + void force_To_MatX_From_Vec_Signed(); + void force_To_MatX_From_MatX_Signed_Entry(); + void force_To_MatX_From_TenXY_Signed_Entry(); + void force_To_MatX_From_Alt_Signed_Entry(); + void force_To_MatX_From_Cls_Signed_Entry(); + + switch (matX->x->gen.tag.type) { + case SIGNX : + matX->force = force_To_MatX_From_SignX_Entry; + break; + case DIGSX : + matX->force = force_To_MatX_From_DigsX_Signed; + break; + case ALT : + matX->force = force_To_MatX_From_Alt_Signed_Entry; + break; + case VECTOR : + matX->force = force_To_MatX_From_Vec_Signed; + break; + case MATX : + matX->force = force_To_MatX_From_MatX_Signed_Entry; + break; + case TENXY : + matX->force = force_To_MatX_From_TenXY_Signed_Entry; + break; + case CLOSURE : + matX->force = force_To_MatX_From_Cls_Signed_Entry; + break; + default : + Error(FATAL, E_INT, "setMatXMethodSigned", "something wrong with x"); + break; + } +} + +void +setMatXMethodUnsigned(MatX *matX) +{ + void force_To_MatX_From_SignX_Entry(); + void force_To_MatX_From_DigsX_Entry(); + void force_To_MatX_From_Vec(); + void force_To_MatX_From_MatX(); + void force_To_MatX_From_TenXY(); + void force_To_MatX_From_Alt_Entry(); + void force_To_MatX_From_Cls_Entry(); + + switch (matX->x->gen.tag.type) { + case SIGNX : + Error(FATAL, E_INT, "setMatXMethodUnsigned", "x is signed"); + break; + case DIGSX : + matX->force = force_To_MatX_From_DigsX_Entry; + break; + case ALT : + matX->force = force_To_MatX_From_Alt_Entry; + break; + case VECTOR : + matX->force = force_To_MatX_From_Vec; + break; + case MATX : + matX->force = force_To_MatX_From_MatX; + break; + case TENXY : + matX->force = force_To_MatX_From_TenXY; + break; + case CLOSURE : + matX->force = force_To_MatX_From_Cls_Entry; + break; + default : + Error(FATAL, E_INT, "setMatXMethodUnsigned", "something wrong with x"); + break; + } +} + +void +absorbDigsXIntoMatX(MatX *matX) +{ + DigsX *digsX; + SmallMatrix smallAccumMat; + + digsX = (DigsX *) matX->x; + + /* + * Now accumulate the digits into a matrix (large or small integers) + * and augment the matrix (matX) with the information. + */ + if (digsX->count > 0) { +#ifdef PACK_DIGITS + if (digsX->count <= DIGITS_PER_WORD) { + makeSmallMatrixFromDigits(smallAccumMat, digsX); + multVectorPairTimesSmallMatrix(matX->mat[0], matX->mat[1], + smallAccumMat); + } + else { +#endif + makeMatrixFromDigits(bigTmpMat, digsX); + multVectorPairTimesMatrix(matX->mat[0], matX->mat[1], bigTmpMat); +#ifdef PACK_DIGITS + } +#endif + matX->x = digsX->x; +#ifdef DAVINCI + beginGraphUpdate(); + deleteOnlyEdge(matX, digsX); + newEdgeToOnlyChild(matX, digsX->x); + endGraphUpdate(); +#endif + + /* + * Now try to remove powers of 2 from the residual matrix. + */ + normalizeMatrix(matX->mat); + + } + +#ifdef TRACE + debugp("force_To_MatX_From_DigsX", + "%x %x absorbed=%d\n", + (unsigned) matX, + (unsigned) digsX, + digsX->count); +#endif +} -- cgit v1.2.3