/*************************************************************************** ** *A ediv.c EDIM-mini-package Frank Lübeck ** ** *Y Copyright (C) 1999 Lehrstuhl D f\"ur Mathematik, RWTH Aachen ** ** `ElementaryDivisorsPPartRkExpSmall' as kernel function. **
*/
/* read GAP source header files with a combined header file */
#include"compiled.h"/* GAP headers */
#include <stdio.h> #include <limits.h>
/* the functions */
/* a helper function for computing k^-1 mod p */ long invmodpcint(long k, long p)
{ long f, g, h, fk, gk, hk, q; if (0 <= k) {
f = k;
fk = 1;
} else {
f = -k;
fk = -1;
}
g = p;
gk = 0; while (g != 0) {
q = f/g;
h = g;
hk = gk;
g = f - q * g;
gk = fk - q * gk;
f = h;
fk = hk;
} return fk % p;
}
/* This function is transformed from a stand alone C-program, which looks very much like the corresponding GAP-function.
Instead of 'malloc' we use here 'NewBag' with type 'T_DATOBJ'. */
Obj FuncElementaryDivisorsPPartRkExpSmall(
Obj self,
Obj A,
Obj pobj,
Obj rkobj,
Obj robj,
Obj ilobj) /* info level */
{ unsignedlong m, n, nn, r, rk, ch, chmax, p, pr, i, j,
ii, i0, i1, x, c, pos, il; unsignedlong *A1, *A2, *Tp, *res, *inv, *vv;
Obj A1obj, A2obj, Tpobj, resobj, invobj, probj, obj, row;
/* change args */ if (! (IS_PLIST(A) || IS_POSOBJ(A)) || LEN_PLIST(A) < 1 ||
! (IS_PLIST(A) || IS_POSOBJ(ELM_PLIST(A, 1)))) {
ErrorQuit("A must be an integer matrix",0L,0L);
}
m = (unsignedlong) LEN_PLIST(A);
n = (unsignedlong) LEN_PLIST(ELM_PLIST(A, 1)); if (! IS_INTOBJ(pobj)) {
ErrorQuit("p must be a small integer (not a %s)",(Int)TNAM_OBJ(pobj),0L);
}
p = (unsignedlong) INT_INTOBJ(pobj); if (! IS_INTOBJ(rkobj)) {
ErrorQuit("rk must be a small integer (not a %s)",(Int)TNAM_OBJ(rkobj),0L);
}
rk = (unsignedlong) INT_INTOBJ(rkobj); if (! IS_INTOBJ(robj)) {
ErrorQuit("r must be a small integer (not a %s)",(Int)TNAM_OBJ(robj),0L);
}
r = (unsignedlong) INT_INTOBJ(robj); if (! IS_INTOBJ(ilobj)) {
ErrorQuit("il must be a small integer (not a %s)",(Int)TNAM_OBJ(ilobj),0L);
}
il = (unsignedlong) INT_INTOBJ(ilobj);
/* pr = p^(r+1) */
probj = PowInt(pobj, SumInt(robj, INTOBJ_INT(1))); if (! IS_INTOBJ(probj)) {
ErrorQuit("exponent too large, see ?ElementaryDivisorsPPartRkExpSmall",0L,0L);
} /* p^(r+1)-1 must fit at least (p-1) times into an unsigned long */
pr = (unsignedlong) INT_INTOBJ(probj); if (ULONG_MAX/(pr-1) < (p-1)) {
ErrorQuit("exponent too large, see ?ElementaryDivisorsPPartRkExpSmall",0L,0L);
} /* max sum of coeffs of numbers of size (p^(r+1)-1) before reduction is
necessary to avoid integer overflow */
chmax = ULONG_MAX/(pr-1)-1;
A2obj = NewBag(T_DATOBJ, (n+1)*(m+1)*sizeof(unsignedlong));
A2 = (unsignedlong *)ADDR_OBJ(A2obj);
A2[0] = m;
nn = n+1; /* reduce matrix entries modulo p^(r+1) */ for (i=1; i<=m; i++) {
row = ELM_PLIST(A, i); if (! IS_PLIST(row) || LEN_PLIST(row) < n) {
ErrorQuit("A must be an integer matrix",0L,0L);
} for (j=1; j<=n; j++) {
obj = ELM_PLIST(ELM_PLIST(A, i), j); if (!(IS_INTOBJ(obj) || TNUM_OBJ(obj)==T_INTPOS || TNUM_OBJ(obj)==T_INTNEG)) {
ErrorQuit("matrix entry must be integer (not a %s)",
(Int)TNAM_OBJ(obj),0L);
} if (LtInt(probj, obj) || LtInt(obj, INTOBJ_INT(0))) {
obj = ModInt(obj, probj); /* this could have changed because of a garbage collection */
A2 = (unsignedlong *)ADDR_OBJ(A2obj);
A2[i*nn+j] = (unsignedlong) INT_INTOBJ(obj);
} else {
A2 = (unsignedlong *)ADDR_OBJ(A2obj);
A2[i*nn+j] = (unsignedlong) INT_INTOBJ(obj);
}
}
}
/* from now on the pointers above are safe: we only manipulate the data in the allocated bags and don't use any GAP function which could cause
a garbage collection */ for (j=1; j<=n; Tp[j]=j, j++);
while (A1[0]<rk && r+1>0) { if (il>0) {fprintf(stderr, "#"); fflush(stderr);}
i0 = A2[0];
A2[0] = 0; for (ii=1; ii<=i0; ii++) {
vv = A2+ii*nn; /* ch counts how many times p^(r+1) the biggest possible entry of
v is */ for (i=1, ch=1; i<=A1[0]; i++) {
c = ((vv[Tp[i]] % p)*(p-inv[i])) % p; if (c != 0) {
ch += c; if (ch>=chmax){ /* reduce the entries */ for (j=1; j<=n; vv[j] %= pr, j++);
ch = c+1;
} for (j=1; j<=n; j++) {
vv[j] += (c * A1[i*nn+j]);
}
}
} for (j=1; j<=n; vv[j] %= pr, j++); for (j=pos=A1[0]+1; (pos<=n) && (vv[Tp[pos]]%p == 0); pos++); if (pos>n) { if (il>0) {fprintf(stderr, "-");fflush(stderr);}
A2[0]++;
i1 = A2[0]; for (j=1; j<=n; j++) {
A2[i1*nn+j] = vv[j]/p;
}
} else { if (il>0) {fprintf(stderr, "+");fflush(stderr);}
A1[0]++;
i1 = A1[0]; for (j=1; j<=n; j++) {
A1[i1*nn+j] = vv[j];
} if (pos != i1) {
x = Tp[i1];
Tp[i1] = Tp[pos];
Tp[pos] = x;
}
inv[i1] = invmodpcint(A1[i1*nn+Tp[i1]] % p, p);
}
}
res[0]++; if (il>0) {fprintf(stderr, "\n#Rank found: %ld\n", A1[0]); fflush(stderr);}
res[res[0]] = rk-A1[0];
r--;
} if (A1[0]==rk) {
RetypeBag(resobj, T_PLIST);
i0 = res[0];
SET_LEN_PLIST(resobj, i0); for (i=1; i<=i0; i++) {
SET_ELM_PLIST(resobj, i, INTOBJ_INT(res[i]));
}
} else { if (il>0) {
fprintf(stderr, "#exponent too small or rank too big. \n");
fflush(stderr);
}
resobj = Fail;
} return resobj;
}
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 ist noch experimentell.