/**************************************************************************** ** *FEqListList(<listL>,<listR>).........testiftwolistsareequal ** **'EqListList'returns'true'ifthetwolists<listL>and<listR>are **equaland'false'otherwise.Thisisagenericfunction,whichworksfor **alltypesoflists.
*/ Int EqListList (
Obj listL,
Obj listR )
{ Int lenL; // length of the left operand Int lenR; // length of the right operand
Obj elmL; // element of the left operand
Obj elmR; // element of the right operand Int i; // loop variable
// get the lengths of the lists and compare them
lenL = LEN_LIST( listL );
lenR = LEN_LIST( listR ); if ( lenL != lenR ) { return0;
}
// loop over the elements and compare them for ( i = 1; i <= lenL; i++ ) {
elmL = ELMV0_LIST( listL, i );
elmR = ELMV0_LIST( listR, i ); if ( elmL == 0 && elmR != 0 ) { return0;
} elseif ( elmR == 0 && elmL != 0 ) { return0;
} elseif ( ! EQ( elmL, elmR ) ) { return0;
}
}
// no differences found, the lists are equal return1;
}
/**************************************************************************** ** *FLtListList(<listL>,<listR>).........testiftwolistsareequal ** **'LtListList'returns'true'ifthelist<listL>islessthanthelist **<listR>and'false'otherwise.Thisisagenericfunction,whichworks **foralltypesoflists.
*/ Int LtListList (
Obj listL,
Obj listR )
{ Int lenL; // length of the left operand Int lenR; // length of the right operand
Obj elmL; // element of the left operand
Obj elmR; // element of the right operand Int i; // loop variable
// get the lengths of the lists and compare them
lenL = LEN_LIST( listL );
lenR = LEN_LIST( listR );
// loop over the elements and compare them for ( i = 1; i <= lenL && i <= lenR; i++ ) {
elmL = ELMV0_LIST( listL, i );
elmR = ELMV0_LIST( listR, i ); if ( elmL == 0 && elmR != 0 ) { return1;
} elseif ( elmR == 0 && elmL != 0 ) { return0;
} elseif ( ! EQ( elmL, elmR ) ) { return LT( elmL, elmR );
}
}
// reached the end of at least one list return (lenL < lenR);
}
Obj SumSclList (
Obj listL,
Obj listR )
{
Obj listS; // sum, result
Obj elmS; // one element of sum list
Obj elmR; // one element of right operand Int len; // length Int i; // loop variable
// make the result list
len = LEN_LIST( listR );
listS = NEW_PLIST_WITH_MUTABILITY( IS_MUTABLE_OBJ(listL) || IS_MUTABLE_OBJ(listR),
T_PLIST, len );
SET_LEN_PLIST( listS, len );
// loop over the entries and add for ( i = 1; i <= len; i++ ) {
elmR = ELMV0_LIST( listR, i ); if (elmR)
{
elmS = SUM( listL, elmR );
SET_ELM_PLIST( listS, i, elmS );
CHANGED_BAG( listS );
}
}
return listS;
}
Obj SumListScl (
Obj listL,
Obj listR )
{
Obj listS; // sum, result
Obj elmS; // one element of sum list
Obj elmL; // one element of left operand Int len; // length Int i; // loop variable
// make the result list
len = LEN_LIST( listL );
listS = NEW_PLIST_WITH_MUTABILITY( IS_MUTABLE_OBJ(listR) || IS_MUTABLE_OBJ(listL),
T_PLIST, len );
SET_LEN_PLIST( listS, len );
// loop over the entries and add for ( i = 1; i <= len; i++ ) {
elmL = ELMV0_LIST( listL, i ); if (elmL)
{
elmS = SUM( elmL, listR );
SET_ELM_PLIST( listS, i, elmS );
CHANGED_BAG( listS );
}
}
return listS;
}
Obj SumListList (
Obj listL,
Obj listR )
{
Obj listS; // sum, result
Obj elmS; // one element of the sum
Obj elmL; // one element of the left list
Obj elmR; // one element of the right list Int lenL,lenR, lenS;// lengths Int i; // loop variable
UInt mutS;
// make the result list -- same mutability as argument
len = LEN_LIST( list ); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(IS_MUTABLE_OBJ(list), T_PLIST_EMPTY, 0);
}
res = NEW_PLIST_WITH_MUTABILITY( IS_MUTABLE_OBJ(list), T_PLIST, len );
SET_LEN_PLIST( res, len );
// enter zeroes everywhere // For now, lets just do the simplest and safest thing for (i = 1; i <= len; i++ )
{
Obj tmp = ELM0_LIST( list, i); if (tmp) {
tmp = ZERO_SAMEMUT(tmp);
SET_ELM_PLIST( res, i,tmp );
CHANGED_BAG( res);
}
} // Now adjust the result TNUM info
static Obj ZeroListMutDefault(Obj list)
{
Obj res; // Obj elm; Int len; Int i;
// make the result list -- always mutable
len = LEN_LIST( list ); if (len == 0) { return NewEmptyPlist();
}
res = NEW_PLIST( T_PLIST ,len );
SET_LEN_PLIST( res, len );
// enter zeroes everywhere // For now, lets just do the simplest and safest thing for (i = 1; i <= len; i++ )
{
Obj tmp = ELM0_LIST( list, i); if (tmp) {
tmp = ZERO_MUT(tmp);
SET_ELM_PLIST( res, i,tmp );
CHANGED_BAG( res);
}
} // Now adjust the result TNUM info
/* This is intended to be installed as a method for the Attribute Zero, for rectangularmatrices ratherthantheOperationZeroOp.Thisisusefulbecause,knowingthat wewantanimmutableresult,wecan(a)reuseasinglerowofzeros
(b) record that the result is a rectangular table */
static Obj FuncZERO_ATTR_MAT(Obj self, Obj mat)
{
Obj zrow;
UInt len;
UInt i;
Obj res;
len = LEN_LIST(mat); if (len == 0) return NewImmutableEmptyPlist();
zrow = ZERO_SAMEMUT(ELM_LIST(mat,1));
CheckedMakeImmutable(zrow);
res = NEW_PLIST_IMM(T_PLIST_TAB_RECT, len);
SET_LEN_PLIST(res,len); for (i = 1; i <= len; i++)
SET_ELM_PLIST(res,i,zrow); return res;
}
static Obj AInvMutListDefault(Obj list)
{
Obj res;
Obj elm; Int len; Int i;
/* make the result list -- always mutable, since this might be a method for
AdditiveInverseOp */
len = LEN_LIST( list ); if (len == 0) { return NewEmptyPlist();
}
res = NEW_PLIST( T_PLIST , len );
SET_LEN_PLIST( res, len );
// enter the additive inverses everywhere for ( i = 1; i <= len; i++ ) {
elm = ELM0_LIST( list, i ); if (elm) {
elm = AINV_MUT( elm );
SET_ELM_PLIST( res, i, elm );
CHANGED_BAG( res );
}
}
static Obj AInvListDefault(Obj list)
{
Obj res;
Obj elm; Int len; Int i;
// make the result list -- same mutability as input
len = LEN_LIST( list ); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(IS_MUTABLE_OBJ(list), T_PLIST_EMPTY, 0);
}
res = NEW_PLIST_WITH_MUTABILITY( IS_MUTABLE_OBJ(list), T_PLIST, len );
SET_LEN_PLIST( res, len );
// enter the additive inverses everywhere for ( i = 1; i <= len; i++ ) {
elm = ELM0_LIST( list, i ); if (elm) {
elm = AINV_SAMEMUT( elm );
SET_ELM_PLIST( res, i, elm );
CHANGED_BAG( res );
}
}
Obj DiffSclList (
Obj listL,
Obj listR )
{
Obj listD; // difference, result
Obj elmD; // one element of difference list
Obj elmR; // one element of right operand Int len; // length Int i; // loop variable Int mut;
// make the result list
len = LEN_LIST( listR );
mut = IS_MUTABLE_OBJ(listL) || IS_MUTABLE_OBJ(listR); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST_EMPTY, 0);
}
listD = NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST, len);
SET_LEN_PLIST( listD, len );
// loop over the entries and subtract for ( i = 1; i <= len; i++ ) {
elmR = ELMV0_LIST( listR, i ); if (elmR)
{
elmD = DIFF( listL, elmR );
SET_ELM_PLIST( listD, i, elmD );
CHANGED_BAG( listD );
}
}
Obj DiffListScl (
Obj listL,
Obj listR )
{
Obj listD; // difference, result
Obj elmD; // one element of difference list
Obj elmL; // one element of left operand Int len; // length Int i; // loop variable Int mut;
// make the result list
len = LEN_LIST( listL );
mut = IS_MUTABLE_OBJ(listL) || IS_MUTABLE_OBJ(listR); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST_EMPTY, 0);
}
listD = NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST, len);
SET_LEN_PLIST( listD, len );
// loop over the entries and subtract for ( i = 1; i <= len; i++ ) {
elmL = ELMV0_LIST( listL, i ); if (elmL)
{
elmD = DIFF( elmL, listR );
SET_ELM_PLIST( listD, i, elmD );
CHANGED_BAG( listD );
}
Obj DiffListList (
Obj listL,
Obj listR )
{
Obj listD; // difference, result
Obj elmD; // one element of the difference
Obj elmL; // one element of the left list
Obj elmR; // one element of the right list Int i; // loop variable
UInt mutD; Int mut;
// Sort out mutability
mutD = 0; for (i = 1; i <= lenL; i++) if ((elmL = ELM0_LIST( listL, i)))
{
mutD = IS_MUTABLE_OBJ(elmL); break;
} for (i = 1; i <= lenR; i++) if ((elmR = ELM0_LIST( listR, i)))
{
mutD = mutD || IS_MUTABLE_OBJ(elmR); break;
}
// loop over the entries and subtract for ( i = 1; i <= lenD; i++ ) {
elmL = ELM0_LIST( listL, i );
elmR = ELM0_LIST( listR, i );
// Now compute the result 6 different cases! if (elmL)
{ if (elmR)
elmD= DIFF(elmL,elmR); elseif ( mutD)
elmD = SHALLOW_COPY_OBJ(elmL); else
elmD = elmL;
} elseif (elmR)
{ if (mutD)
elmD = AINV_MUT(elmR); else
elmD = AINV_SAMEMUT(elmR);
} else
elmD = 0;
if (elmD)
{
SET_ELM_PLIST( listD, i, elmD );
CHANGED_BAG( listD );
}
} // Now adjust the result TNUM info. There's not so much we can say // here with total reliability
Obj ProdSclList (
Obj listL,
Obj listR )
{
Obj listP; // product, result
Obj elmP; // one element of product list
Obj elmR; // one element of right operand Int len; // length Int i; // loop variable Int mut;
// make the result list
len = LEN_LIST( listR );
mut = IS_MUTABLE_OBJ(listL) || IS_MUTABLE_OBJ(listR); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST_EMPTY, 0);
}
listP = NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST, len);
SET_LEN_PLIST( listP, len );
// loop over the entries and multiply for ( i = 1; i <= len; i++ ) {
elmR = ELMV0_LIST( listR, i ); if (elmR)
{
elmP = PROD( listL, elmR );
SET_ELM_PLIST( listP, i, elmP );
CHANGED_BAG( listP );
}
} if (IS_PLIST( listR ))
{ if (HAS_FILT_LIST(listR, FN_IS_DENSE))
SET_FILT_LIST( listP, FN_IS_DENSE ); elseif (HAS_FILT_LIST(listR, FN_IS_NDENSE))
SET_FILT_LIST( listP, FN_IS_NDENSE );
}
return listP;
}
Obj ProdListScl (
Obj listL,
Obj listR )
{
Obj listP; // product, result
Obj elmP; // one element of product list
Obj elmL; // one element of left operand Int len; // length Int i; // loop variable Int mut;
// make the result list
len = LEN_LIST( listL );
mut = IS_MUTABLE_OBJ(listL) || IS_MUTABLE_OBJ(listR); if (len == 0) { return NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST_EMPTY, 0);
}
listP = NEW_PLIST_WITH_MUTABILITY(mut, T_PLIST, len);
SET_LEN_PLIST( listP, len );
// loop over the entries and multiply for ( i = 1; i <= len; i++ ) {
elmL = ELMV0_LIST( listL, i ); if (elmL) {
elmP = PROD( elmL, listR );
SET_ELM_PLIST( listP, i, elmP );
CHANGED_BAG( listP );
}
}
Obj ProdListList (
Obj listL,
Obj listR )
{
Obj listP; // product, result
Obj elmP; // one summand of the product
Obj elmL; // one element of the left list
Obj elmR; // one element of the right list Int lenL,lenR,len; // length Int i; // loop variable Int imm;
// get and check the length
lenL = LEN_LIST( listL );
lenR = LEN_LIST( listR );
len = (lenL < lenR) ? lenL : lenR; // loop over the entries and multiply and accumulate
listP = 0;
imm = 0; for (i = 1; i <= len; i++)
{
elmL = ELM0_LIST( listL, i );
elmR = ELM0_LIST( listR, i ); if (elmL && elmR)
{
elmP = PROD( elmL, elmR ); if (listP)
listP = SUM( listP, elmP ); else
{
listP = elmP;
imm = !IS_MUTABLE_OBJ(listP);
}
}
}
// TODO: This is possible expensive, we may be able to settle for // a cheaper check and call MakeImmutable() instead. if (imm && IS_MUTABLE_OBJ(listP))
CheckedMakeImmutable(listP);
if (!listP)
ErrorMayQuit("Inner product multiplication of lists: no summands", 0, 0);
static Obj OneMatrix(Obj mat, UInt mut)
{
Obj res = 0; // one, result
Obj row; // one row of the result
Obj zero = 0; // zero element
Obj one = 0; // one element
UInt len; // length (and width) of matrix
UInt i, k; // loop variables BOOL rmut; // rows of result mutable? BOOL cmut; // result mutable?
GAP_ASSERT(mut <= 2);
// check that the operand is a *square* matrix
len = LEN_LIST( mat ); if ( len != LEN_LIST( ELM_LIST( mat, 1 ) ) ) {
ErrorMayQuit("Matrix ONE: <mat> must be square (not %d by %d)",
(Int)len, (Int)LEN_LIST(ELM_LIST(mat, 1)));
}
// get the zero and the one switch (mut) { case0:
zero = ZERO_MUT( ELM_LIST( ELM_LIST( mat, 1 ), 1 ) );
one = ONE_SAMEMUT(zero);
CheckedMakeImmutable(zero);
CheckedMakeImmutable(one);
cmut = rmut = FALSE; break;
case2:
zero = ZERO_SAMEMUT( ELM_LIST( ELM_LIST( mat, 1 ), 1 ) );
one = ONE( zero );
cmut = rmut = TRUE; break;
}
// make the identity matrix
res = NEW_PLIST(T_PLIST, len);
SET_LEN_PLIST( res, len ); for ( i = 1; i <= len; i++ ) {
row = NEW_PLIST(T_PLIST, len);
SET_LEN_PLIST( row, len ); for ( k = 1; k <= len; k++ )
SET_ELM_PLIST( row, k, zero );
SET_ELM_PLIST( row, i, one ); if (!rmut)
MakeImmutableNoRecurse(row);
SET_ELM_PLIST( res, i, row );
CHANGED_BAG( res );
} if (!cmut)
MakeImmutableNoRecurse(res);
static Obj InvMatrix(Obj mat, UInt mut)
{
Obj res = 0; // power, result
Obj row; // one row of the matrix
Obj row2; // another row of the matrix
Obj elm; // one element of the matrix
Obj elm2; // another element of the matrix
Obj zero = 0; // zero element
Obj one = 0; // one element
UInt len; // length (and width) of matrix
UInt i, k, l; // loop variables BOOL rmut; // rows of result mutable? BOOL cmut; // result mutable?
GAP_ASSERT(mut <= 2);
// check that the operand is a *square* matrix
len = LEN_LIST( mat ); if ( len != LEN_LIST( ELM_LIST( mat, 1 ) ) ) {
ErrorMayQuit("Matrix INV: <mat> must be square (not %d by %d)",
(Int)len, (Int)LEN_LIST(ELM_LIST(mat, 1)));
}
// get the zero and the one switch (mut) { case0:
zero = ZERO_MUT( ELM_LIST( ELM_LIST( mat, 1 ), 1 ) );
one = ONE_SAMEMUT(zero);
CheckedMakeImmutable(zero);
CheckedMakeImmutable(one);
cmut = rmut = FALSE; break;
case2:
zero = ZERO_SAMEMUT( ELM_LIST( ELM_LIST( mat, 1 ), 1 ) );
one = ONE( zero );
cmut = rmut = TRUE; break;
}
// make a matrix of the form $ ( Id_<len> | <mat> ) $
res = NEW_PLIST(T_PLIST, len);
SET_LEN_PLIST(res, len); for (i = 1; i <= len; i++) {
row = NEW_PLIST(T_PLIST, 2 * len);
SET_LEN_PLIST(row, 2 * len);
SET_ELM_PLIST(res, i, row);
CHANGED_BAG(res);
} for ( i = 1; i <= len; i++ ) {
row = ELM_PLIST( res, i ); for ( k = 1; k <= len; k++ )
SET_ELM_PLIST( row, k, zero );
SET_ELM_PLIST( row, i, one );
} for ( i = 1; i <= len; i++ ) {
row = ELM_PLIST( res, i );
row2 = ELM_LIST( mat, i ); for ( k = 1; k <= len; k++ ) {
SET_ELM_PLIST( row, k + len, ELM_LIST( row2, k ) );
CHANGED_BAG( row );
}
}
// make row operations to reach form $ ( <inv> | Id_<len> ) $ // loop over the columns of <mat> for ( k = len+1; k <= 2*len; k++ ) {
// find a nonzero entry in this column for ( i = k-len; i <= len; i++ ) { if ( ! EQ( ELM_PLIST( ELM_PLIST(res,i), k ), zero ) ) break;
} if ( len < i ) { return Fail;
}
// make the row the <k>-th row and normalize it
row = ELM_PLIST( res, i );
SET_ELM_PLIST( res, i, ELM_PLIST( res, k-len ) );
SET_ELM_PLIST( res, k-len, row ); if (mut < 2)
elm2 = INV_SAMEMUT( ELM_PLIST( row, k ) ); else
elm2 = INV( ELM_PLIST( row, k ) ); for ( l = 1; l <= 2*len; l++ ) {
elm = PROD( elm2, ELM_PLIST( row, l ) );
SET_ELM_PLIST( row, l, elm );
CHANGED_BAG( row );
}
// clear all entries in this column for ( i = 1; i <= len; i++ ) {
row2 = ELM_PLIST( res, i ); if (mut < 2)
elm = AINV_MUT( ELM_PLIST( row2, k ) ); else
elm = AINV_SAMEMUT( ELM_PLIST( row2, k ) ); if ( i != k-len && ! EQ(elm,zero) ) { for ( l = 1; l <= 2*len; l++ ) {
elm2 = PROD( elm, ELM_PLIST( row, l ) );
elm2 = SUM( ELM_PLIST( row2, l ), elm2 );
SET_ELM_PLIST( row2, l, elm2 );
CHANGED_BAG( row2 );
}
}
}
}
// throw away the right halves of each row for ( i = 1; i <= len; i++ ) {
row = ELM_PLIST(res, i);
SET_LEN_PLIST(row, len);
SHRINK_PLIST(row, len); if (!rmut)
MakeImmutableNoRecurse(row);
} if (!cmut)
MakeImmutableNoRecurse(res);
static Obj FuncPROD_VEC_MAT_DEFAULT(Obj self, Obj vec, Obj mat)
{
Obj res;
Obj elt;
Obj vecr;
UInt i,len;
Obj z;
res = (Obj) 0;
len = LEN_LIST(vec);
RequireSameLength("<vec> * <mat>", vec, mat);
elt = ELMW_LIST(vec,1);
z = ZERO_SAMEMUT(elt); for (i = 1; i <= len; i++)
{
elt = ELMW_LIST(vec,i); if (!EQ(elt,z))
{
vecr = ELMW_LIST(mat,i);
if (res == (Obj)0)
{
res = SHALLOW_COPY_OBJ(vecr);
CALL_2ARGS(MultVectorLeftOp, res, elt);
}
else
CALL_3ARGS(AddRowVectorOp, res, vecr, elt);
}
}
if (res == (Obj)0)
res = ZERO_SAMEMUT(ELMW_LIST(mat,1));
if (!IS_MUTABLE_OBJ(vec) && !IS_MUTABLE_OBJ(mat))
CheckedMakeImmutable(res);
return res;
}
/****************************************************************************
**
*F FuncINV_MAT_DEFAULT
**
** A faster version of InvMat for those matrices for whose rows AddRowVector
** and MultVectorLeft make sense (and might have fast kernel methods)
**
*/
static Obj ConvertToMatrixRep;
static Obj InvMatWithRowVecs(Obj mat, UInt mut)
{
Obj res; // result
Obj matcopy; // copy of mat
Obj row = 0; // one row of matcopy
Obj row2; // corresponding row of res
Obj row3; // another row of matcopy
Obj x = 0; // one element of the matrix
Obj xi; // 1/x
Obj y; // another element of the matrix
Obj yi; // -y
Obj zero; // zero element
Obj zerov; // zero vector
Obj one; // one element
UInt len; // length (and width) of matrix
UInt i, k, j; // loop variables
// check that the operand is a *square* matrix
len = LEN_LIST( mat );
if ( len != LEN_LIST( ELM_LIST( mat, 1 ) ) ) {
ErrorMayQuit("Matrix INV: <mat> must be square (not %d by %d)",
(Int)len, (Int)LEN_LIST(ELM_LIST(mat, 1)));
}
// get the zero and the one
zerov = ZERO_SAMEMUT(ELMW_LIST(mat, 1));
zero = ZERO_SAMEMUT(ELMW_LIST(ELMW_LIST(mat, 1), 1));
one = ONE( zero );
// set up res (initially the identity) and matcopy
res = NEW_PLIST(T_PLIST,len);
matcopy = NEW_PLIST(T_PLIST,len);
SET_LEN_PLIST(res,len);
SET_LEN_PLIST(matcopy,len);
for (i = 1; i <= len; i++)
{
row = SHALLOW_COPY_OBJ(zerov);
ASS_LIST(row,i,one);
SET_ELM_PLIST(res,i,row);
CHANGED_BAG(res);
row = SHALLOW_COPY_OBJ(ELM_LIST(mat,i));
SET_ELM_PLIST(matcopy,i,row);
CHANGED_BAG(matcopy);
}
/* Now to work, make matcopy an identity by row operations and
do the same row operations to res */
// outer loop over columns of matcopy
for (i = 1; i <= len; i++)
{
// Find a non-zero leading entry that is in that column
for (j = i; j <= len; j++)
{
row = ELM_PLIST(matcopy,j);
x = ELMW_LIST(row,i);
if (!EQ(x,zero))
break;
}
// if there isn't one then the matrix is not invertible
if (j > len)
return Fail;
// Maybe swap two rows
// But I will want this value anyway
row2 = ELM_PLIST(res,j);
if (j != i)
{
SET_ELM_PLIST(matcopy,j,ELM_PLIST(matcopy,i));
SET_ELM_PLIST(res,j,ELM_PLIST(res,i));
SET_ELM_PLIST(matcopy,i,row);
SET_ELM_PLIST(res,i,row2);
}
/*Maybe rescale the row */
if (!EQ(x, one))
{
xi = INV(x);
CALL_2ARGS(MultVectorLeftOp, row, xi);
CALL_2ARGS(MultVectorLeftOp, row2, xi);
}
// Clear the entries. We know that we can ignore the entries in rows i..j
for (k = 1; k < i; k++)
{
row3 = ELM_PLIST(matcopy,k);
y = ELMW_LIST(row3,i);
if (!EQ(y,zero))
{
yi = AINV_SAMEMUT(y);
CALL_3ARGS(AddRowVectorOp, row3, row, yi);
CALL_3ARGS(AddRowVectorOp, ELM_PLIST(res,k), row2, yi);
}
}
for (k = j+1; k <= len; k++)
{
row3 = ELM_PLIST(matcopy,k);
y = ELMW_LIST(row3,i);
if (!EQ(y,zero))
{
yi = AINV_SAMEMUT(y);
CALL_3ARGS(AddRowVectorOp, row3, row, yi);
CALL_3ARGS(AddRowVectorOp, ELM_PLIST(res,k), row2, yi);
}
}
}
// Now we adjust mutability. Couldn't do it earlier, because AddRowVector,
// etc. needs mutable target vectors
switch (mut)
{
case 0:
CheckedMakeImmutable(res);
break;
case 1:
if (IS_MUTABLE_OBJ(mat))
{
if (!IS_MUTABLE_OBJ(ELM_LIST(mat,1)))
for (i = 1; i <= len; i++)
CheckedMakeImmutable(ELM_LIST(res,i));
}
else
CheckedMakeImmutable(res);
break;
case 2:
break;
}
/****************************************************************************
**
*F FuncADD_TO_LIST_ENTRIES_PLIST_RANGE( <list>, <range>, <x> )
**
** This is a method for the operation AddToListEntries, used mainly in
** the MPQS of Stefan Kohl.
**
** This method requires a plain list for the first argument, and a
** range for the second and is optimised for the case where x and the list
** entries are small integers, as are their sums
*/
static Obj
FuncADD_TO_LIST_ENTRIES_PLIST_RANGE(Obj self, Obj list, Obj range, Obj x)
{
UInt low, high, incr;
Obj y,z;
UInt i;
if (!IS_INTOBJ(x))
return TRY_NEXT_METHOD;
low = GET_LOW_RANGE(range);
incr = GET_INC_RANGE(range);
high = low + incr*(GET_LEN_RANGE(range)-1);
for (i = low; i <= high; i+= incr)
{
y = ELM_PLIST(list,i);
if (!IS_INTOBJ(y) ||
!SUM_INTOBJS(z,x,y))
{
z = SUM(x,y);
SET_ELM_PLIST(list,i,z);
CHANGED_BAG(list);
}
else
SET_ELM_PLIST(list,i,z);
}
return (Obj) 0;
}
/****************************************************************************
**
*F MONOM_TOT_DEG_LEX( u, v ) . . . . . total degree lexicographical ordering
**
** This function implements the total degree plus lexicographical ordering
** for monomials of commuting indeterminates. It is in this file because
** monomials are presently implemented as lists of indeterminate-exponent
** pairs. Should there be more functions supporting polynomial arithmetic,
** then this function should go into a separate file.
**
** Examples: x^2y^3 < y^7, x^4 y^5 < x^3 y^6
*/
static Obj FuncMONOM_TOT_DEG_LEX ( Obj self, Obj u, Obj v ) {
Int4 i, lu, lv;
Obj total;
Obj lexico;
if (!IS_PLIST(u) || !IS_DENSE_LIST(u)) {
RequireArgument(SELF_NAME, u, "must be a dense plain list");
}
if (!IS_PLIST(v) || !IS_DENSE_LIST(v)) {
RequireArgument(SELF_NAME, v, "must be a dense plain list");
}
lu = LEN_PLIST( u );
lv = LEN_PLIST( v );
// strip off common prefixes
i = 1;
while ( i <= lu && i <= lv && EQ(ELM_PLIST( u,i ), ELM_PLIST( v,i )) )
i++;
// Is u a prefix of v ? Return true if u is a proper prefix.
if ( i > lu ) return (lu < lv) ? True : False;
// Is v a prefix of u ?
if ( i > lv ) return False;
// Now determine the lexicographic order. The monomial is interpreted
// as a string of indeterminates.
if ( i % 2 == 1 ) {
// The first difference between u and v is an indeterminate.
lexico = LT(ELM_PLIST( u, i ), ELM_PLIST( v, i )) ? True : False;
i++;
}
else {
// The first difference between u and v is an exponent.
lexico = LT(ELM_PLIST( v, i ), ELM_PLIST( u, i )) ? True : False;
}
// Now add up the remaining exponents in order to compare the total
// degrees.
total = INTOBJ_INT(0);
while ( i <= lu && i <= lv ) {
C_SUM_FIA( total, total, ELM_PLIST( u, i ) );
C_DIFF_FIA( total, total, ELM_PLIST( v, i ) );
i += 2;
}
// Only one of the following while loops is executed
while ( i <= lu ) {
C_SUM_FIA( total, total, ELM_PLIST( u, i ) );
i += 2;
}
while ( i <= lv ) {
C_DIFF_FIA( total, total, ELM_PLIST( v, i ) );
i += 2;
}
/****************************************************************************
**
*F MONOM_GRLEX( u, v ) . . . . . ``grlex'' ordering for internal monomials
**
** This function implements the ``grlex'' (degree, then lexicographic) ordering
** for monomials of commuting indeterminates with x_1>x_2>x_3 etc. (this
** is standard textbook usage). It is in this file because
** monomials are presently implemented as lists of indeterminate-exponent
** pairs. Should there be more functions supporting polynomial arithmetic,
** then this function should go into a separate file.
**
** Examples: x^2y^3 < y^7, x^4 y^5 < x^3 y^6
*/
static Obj FuncMONOM_GRLEX( Obj self, Obj u, Obj v ) {
Int4 i, lu, lv;
Obj total,ai,bi;
if (!IS_PLIST(u) || !IS_DENSE_LIST(u)) {
RequireArgument(SELF_NAME, u, "must be a dense plain list");
}
if (!IS_PLIST(v) || !IS_DENSE_LIST(v)) {
RequireArgument(SELF_NAME, v, "must be a dense plain list");
}
lu = LEN_PLIST( u );
lv = LEN_PLIST( v );
// compare the total degrees
total = INTOBJ_INT(0);
for (i=2;i<=lu;i+=2) {
C_SUM_FIA( total, total, ELM_PLIST( u, i ) );
}
for (i=2;i<=lv;i+=2) {
C_DIFF_FIA( total, total, ELM_PLIST( v, i ) );
}
if ( ! (EQ( total, INTOBJ_INT(0))) ) {
// degrees differ, use these
return LT( total, INTOBJ_INT(0)) ? True : False;
}
// now use lexicographic ordering
i=1;
while (i<=lu && i<=lv) {
ai=ELM_PLIST(u,i);
bi=ELM_PLIST(v,i);
if (LT(bi,ai)) {
return True;
}
if (LT(ai,bi)) {
return False;
}
ai=ELM_PLIST(u,i+1);
bi=ELM_PLIST(v,i+1);
if (LT(ai,bi)) {
return True;
}
if (LT(bi,ai)) {
return False;
}
i+=2;
}
if (i<lv) {
return True;
}
return False;
}
/****************************************************************************
**
*F ZIPPED_SUM_LISTS(z1,z2,zero,f)
**
** implements the `ZippedSum' function to add polynomials in external
** representation. This is time critical and thus in the kernel.
** the function assumes that all lists are plists.
*/
static Obj FuncZIPPED_SUM_LISTS( Obj self, Obj z1, Obj z2, Obj zero, Obj f ) {
Int l1,l2,i;
Int i1,i2;
Obj sum,x,y;
Obj cmpfun,sumfun,a,b,c;
l1=LEN_LIST(z1);
l2=LEN_LIST(z2);
cmpfun=ELM_LIST(f,1);
sumfun=ELM_LIST(f,2);
sum=NEW_PLIST(T_PLIST,0);
i1=1;
i2=1;
while ((i1<=l1) && (i2<=l2)) {
// Pr("A= %d %d\n",i1,i2);
// if z1[i1] = z2[i2] then
a=ELM_PLIST(z1,i1);
b=ELM_PLIST(z2,i2);
if (EQ(a,b)) {
// the entries are equal
x=ELM_PLIST(z1,i1+1);
y=ELM_PLIST(z2,i2+1);
// Pr("EQ, %d %d\n",INT_INTOBJ(x),INT_INTOBJ(y));
c=CALL_2ARGS(sumfun,x,y);
if (!(EQ(c,zero))) {
// Pr("Added %d\n",INT_INTOBJ(c), 0);
AddList(sum,a);
AddList(sum,c);
}
i1=i1+2;
i2=i2+2;
}
else {
// compare
a=ELM_PLIST(z1,i1); // in case the EQ triggered a GC
b=ELM_PLIST(z2,i2);
// Pr("B= %d %d\n",ELM_LIST(a,1),ELM_LIST(b,1));
c=CALL_2ARGS(cmpfun,a,b);
// Pr("C= %d %d\n",c, 0);
if ( // this construct is taken from the compiler
(Obj)(UInt)(c != False) ) {
a=ELM_PLIST(z1,i1);
AddList(sum,a);
c=ELM_PLIST(z1,i1+1);
AddList(sum,c);
i1=i1+2;
}
else {
b=ELM_PLIST(z2,i2);
AddList(sum,b);
c=ELM_PLIST(z2,i2+1);
AddList(sum,c);
i2=i2+2;
} // else
} /*else (elif)*/
} // while
for (i=i1;i<l1;i+=2) {
AddList(sum,ELM_PLIST(z1,i));
AddList(sum,ELM_PLIST(z1,i+1));
}
for (i=i2;i<l2;i+=2) {
AddList(sum,ELM_PLIST(z2,i));
AddList(sum,ELM_PLIST(z2,i+1));
}
return sum;
}
/****************************************************************************
**
*F FuncMONOM_PROD(m1,m2)
**
** implements the multiplication of monomials. Both must be plain lists
** of integers.
*/
static Obj FuncMONOM_PROD( Obj self, Obj m1, Obj m2 ) {
// No kernel installations for One or Inverse any more
/* Sum. Here we can do list + non-list and non-list + list,
we have to careful about list+list, though, as it might
really be list+matrix or matrix+list
for the T_PLIST_CYC and T_PLIST_FFE cases, we know the nesting
depth (1) and so we can do the cases of adding them to each
other and to T_PLIST_TAB objects, which have at least nesting
depth 2. Some of this will be overwritten in vector.c and
vecffe.c
everything else needs to wait until the library */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.