Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/nq/src/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 12.0.2024 mit Größe 12 kB image not shown  

Quelle  glimt.c   Sprache: C

 
/*****************************************************************************
**
**    glimt.c                         NQ                       Werner Nickel
**                                         nickel@mathematik.tu-darmstadt.de
*/



#include "nq.h"
#include "time.h"
#include "glimt.h"

#undef min

/*
**    This module uses the arbitrary precision GNU integer package gmp.
*/

#include <gmp.h>

/*
**    Define the data type for large integers and vectors of large integers.
*/

typedef MP_INT  *large;
typedef large   *lvec;

#define NOTZERO(l) ((l)->_mp_size != 0)
#define ISZERO(l)  ((l)->_mp_size == 0)
#define ISNEG(l)   ((l)->_mp_size < 0)
#define NEGATE(l)  ((l)->_mp_size = -(l)->_mp_size)
#define SIGN(l)    (expo)(sgn((l)->_mp_size))
#define SIZE(l)    ((l)->_mp_size)
#define LIMB(l,i)  (expo)((l)->_mp_d[i])


/*
**    The variable 'Matrix' contains the pointer to the integer matrix.
**    The variable 'Heads' contains the pointer to an array whose i-th
**    component contains the position of the first non-zero entry in
**    i-th row of Matrix[]. The variable changedMatrix indicates whether
**    the integer matrix changed during the reduction of an integer
**    vector.
*/

lvec     *Matrix = (lvec*)0;
long     *Heads;
large    MaximalEntry;

static   long     changedMatrix = 0;

/*
**    The number of rows and columns in the integer matrix are stored in
**    the following two variables.
*/

long     NrRows = 0;
long     NrCols = 0;

/*
**    Take the time spend in this package.
*/

static  long Time = 0;

/*
**    Set a flag if the integer matrix is the identity.
**    This can be used as an early stopping criterion.
*/

int     EarlyStop;

/*
**    Set this flag if each non-zero vector handed to addRow() is to
**    be printed to a file.
*/

int     RawMatOutput;
FILE    *RawMatFile = NULL;


static large ltom(expo n) {
 MP_INT  *l = (MP_INT*)Allocate(sizeof(MP_INT));

 /*
** There does not seem to be a function that converts from long long
** to a large integer.  So we have to do it a bit more complicated.
*/

 mpz_init_set_si(l, (int)(n >> 32));
 mpz_mul_2exp(l, l, 32 );
 mpz_add_ui(l, l, (unsigned int)n);

 return l;
}

void freeExpVecs(expvec *M) {
 long    i;

 for (i = 0; i < NrRows; i++) free(M[i]);
 free(M);

 NrRows = NrCols = 0;
}

static void freeVector(lvec v) {
 long    i;

 for (i = 1; i <= NrCols; i++) { mpz_clear(v[i]); Free(v[i]); }
 Free(v);
}

static void freeMatrix(void) {

 long    i;

 if (Matrix == (lvec *)0) return;

 mpz_clear(MaximalEntry);
 Free(MaximalEntry);

 for (i = 0; i < NrRows; i++) freeVector(Matrix[i]);
 Free(Matrix);
 Matrix = (lvec*)0;
}

/*
static void printVector(lvec v) {
long    i;

for (i = 1; i <= NrCols; i++) {
printf(" ");
mpz_out_str(stdout, 10, v[i]);
}
printf("\n");
}
*/


static long survivingCols(expvec *M, long *surviving) {
 long nrSurv = 0, h = 1, i;

 for (i = 0; i < NrRows; i++) {
  for (; h < Heads[i]; h++) surviving[nrSurv++] = h;
  if (M[i][h] != (expo)1)    surviving[nrSurv++] = h;
  h++;
 }
 for (; h <= NrCols; h++) surviving[nrSurv++] = h;
 return nrSurv;
}

static void outputMatrix(expvec *M, const char *suffix) {
 long    i, j, nrSurv, *surviving;
 char    outputName[128];
 FILE    *fp;

 if (strlen(InputFile) > 100)
  sprintf(outputName, "NqOut.%s.%d", suffix, Class + 1);
 else
  sprintf(outputName, "%s.%s.%d", InputFile, suffix, Class + 1);
 if ((fp = fopen(outputName, "w")) == NULL) {
  perror(outputName);
  fprintf(stderr,
          "relation matrix for class %d not written\n"Class + 1);
 }

 if (M == (expvec*)0) {
  fprintf(fp, "0\n");
  fclose(fp);
  return;
 }

 surviving = (long *)Allocate(NrCols * sizeof(long));
 nrSurv = survivingCols(M, surviving);

 fprintf(fp, "%ld # Number of columns\n", nrSurv);
 for (i = 0; i < NrRows; i++) {
  if (M[i][Heads[i]] != (expo)1) {
   for (j = 0; j < nrSurv; j++)
    fprintf(fp, " "EXP_FORMAT, M[i][surviving[j]]);
   fprintf(fp, "\n");
  }
 }

 Free(surviving);
 fclose(fp);
}

void OutputMatrix(const char *suffix) {
 long    i, j;
 char    outputName[128];
 FILE    *fp;

 if (strlen(InputFile) > 100)
  sprintf(outputName, "NqOut.%s.%d", suffix, Class + 1);
 else
  sprintf(outputName, "%s.%s.%d", InputFile, suffix, Class + 1);
 if ((fp = fopen(outputName, "w")) == NULL) {
  perror(outputName);
  fprintf(stderr,
          "relation matrix for class %d not written\n"Class + 1);
 }

 if (Matrix == (lvec*)0) {
  fprintf(fp, "0\n");
  fclose(fp);
  return;
 }

 fprintf(fp, "%ld\n", NrCols);
 for (i = 0; i < NrRows; i++) {
  for (j = 1; j <= NrCols; j++) {
   fputc(' ', fp);
   mpz_out_str(fp, 10, Matrix[i][j]);
  }
  fprintf(fp, "\n");
 }

 fclose(fp);
}

static void printGapMatrix(expvec *M) {
 long    i, j, first, nrSurv, *surviving;

 if (M == (expvec*)0) {
  printf("[\n[");
  for (j = 1; j <= NrCenGens; j++) {
   printf(" 0");
   if (j < NrCenGens) putchar(',');
  }
  printf(" ]\n],\n");
  return;
 }

 surviving = (long *)Allocate(NrCols * sizeof(long));
 nrSurv = survivingCols(M, surviving);

 if (nrSurv == 0) { Free(surviving); return; }

 printf("[\n");
 for (i = 0, first = 1; i < NrRows; i++) {
  if (M[i][Heads[i]] != (expo)1) {
   if (!first) printf(",\n");
   else         first = 0;
   printf("[");
   for (j = 0; j < nrSurv; j++) {
    printf(" "EXP_FORMAT, M[i][surviving[j]]);
    if (j < nrSurv) putchar(',');
   }
   printf("]");
  }
 }
 if (first) {
  printf("[");
  for (j = 0; j < nrSurv - 1; j++) printf(" 0,");
  printf(" 0]\n");
 }
 printf("],");
 putchar('\n');

 Free(surviving);
}

/*
**    Print the contents of Matrix[].
*/

static void printMatrix(void) {

 long    i, j;

 printf(" heads vectors\n");
 for (i = 0; i < NrRows; i++) {
  printf(" %ld ", Heads[i]);
  for (j = 1; j <= NrCols; j++) {
   putchar(' ');
   mpz_out_str(stdout, 10, Matrix[i][j]);
  }
  putchar('\n');
 }
}

/*
**    MatrixToExpVec() converts the contents of Matrix[] to a list of
**    exponent vectors which can be used easily by the elimination
**    routines. It also checks that the integers are not bigger than 2^15.
**    If this is the case it prints a warning and aborts.
*/

expvec *MatrixToExpVecs(void) {

 long    i, j, k;
 large   m;

 expo    c;
 expvec  *M;

 if (NrRows == 0) {
  freeMatrix();
  TimeOutOff();
  if (Gap) printGapMatrix((expvec*)0);
  if (AbelianInv) outputMatrix((expvec*)0, "abinv");
  if (RawMatOutput && RawMatFile != NULL) fclose(RawMatFile);
  TimeOutOn();
  return (expvec*)0;
 }

 M = (expvec*)malloc(NrRows * sizeof(expvec));
 if (M == (expvec*)0) { perror("MatrixToExpVecs(), M"); exit(2); }

 /* Convert. */
 for (i = 0; i < NrRows; i++) {
  M[i] = (expvec)calloc(NrCols + 1, sizeof(expo));
  if (M[i] == (expvec)0) {
   perror("MatrixToExpVecs(), M[]");
   exit(2);
  }
  for (j = Heads[i]; j <= NrCols; j++) {
   m = Matrix[i][j];
   if (mpz_sizeinbase(m, 2) > 8 * sizeof(signed int) - 2) {
    printf("Warning, Exponent too large.\n");
    printMatrix();
    exit(4);
   }
   M[i][j] = mpz_get_si(m);
  }
 }
 for (i = 0; i < NrRows; i++) freeVector(Matrix[i]);

 /* Make all entries except the head entries negative. */
 for (i = 0; i < NrRows; i++)
  for (j = i - 1; j >= 0; j--)
   if (abs(M[j][ Heads[i] ]) >= M[i][ Heads[i] ] ||
           M[j][ Heads[i] ] > (expo)0) {
    c = M[j][ Heads[i] ] / M[i][ Heads[i] ];
    if (M[j][ Heads[i] ] > (expo)0 &&
            M[j][ Heads[i] ] % M[i][ Heads[i] ] != (expo)0) c++;
    for (k = Heads[i]; k <= NrCols; k++)
     M[j][k] -= c * M[i][k];
   }

 free(Matrix);
 Matrix = (lvec *)0;

 printf("# Time spent on the integer matrix: %ld msec.\n", Time);
 printf("# Maximal entry: ");
 mpz_out_str(stdout, 10, MaximalEntry);
 printf("\n");


 TimeOutOff();
 if (Gap) printGapMatrix(M);
 if (AbelianInv) outputMatrix(M, "abinv");
 TimeOutOn();

 if (RawMatOutput) fclose(RawMatFile);

 return M;
}

/*
**    The following routines perform operations with vectors :
**
**    vNeg()  negates each entry of the vector v starting at v[a].
**    vSub()  subtracts a multiple of the vector w from the vector v.
**            The scalar w is multiplied with is v[a]/w[a], so that
**            the entry v[a] after the subtraction is smaller than
**            w[a].
**    vSubOnce()  subtracts the vector w from the vector v.
*/

static void vNeg(lvec v, long a) {
 while (a <= NrCols) {
  NEGATE(v[a]);
  a++;
 }
}

/*
static void vSubOnce(lvec v, lvec w, long a) {
while (a <= NrCols) {
mpz_sub(v[a], w[a], v[a]);
a++;
}
}
*/


static void vSub(lvec v, lvec w, long a) {
 mpz_t    q, t;

 if (NOTZERO(v[a])) {
  mpz_init(q);

  mpz_tdiv_q(q, v[a], w[a]);
  if (NOTZERO(q)) {
   mpz_init(t);

   while (a <= NrCols) {
    mpz_mul(t,    q,    w[a]);
    mpz_sub(v[a], v[a], t);

    mpz_abs(t, v[a]);
    if (mpz_cmp(t, MaximalEntry) > 0)
     mpz_set(MaximalEntry, v[a]);

    a++;
   }

   mpz_clear(t);
  }

  mpz_clear(q);
 }
}

static void lastReduce(void) {

 long    i, j;

 /* Reduce all the head columns. */
 for (i = 0; i < NrRows; i++)
  for (j = i - 1; j >= 0; j--)
   vSub(Matrix[j], Matrix[i], Heads[i]);
}

/*
**    vReduce() reduces the vector v against the vectors in Matrix[].
*/

static lvec vReduce(lvec v, long h) {
 long    i;
 lvec    w;

 for (i = 0; i < NrRows && Heads[i] <= h; i++) {
  if (Heads[i] == h) {
   while (NOTZERO(v[h]) && NOTZERO(Matrix[i][h])) {
    vSub(v, Matrix[i], h);
    if (NOTZERO(v[h])) {
     changedMatrix = 1;
     vSub(Matrix[i], v, h);
    }
   }
   if (NOTZERO(v[h])) {  /* v replaces th i-th row. */
    if (ISNEG(v[h])) vNeg(v, h);
    w = Matrix[i];
    Matrix[i] = v;
    v = w;
   }

   while (h <= NrCols && ISZERO(v[h])) h++;
   if (h > NrCols) { freeVector(v); v = (lvec)0; }
  }
 }

 return v;
}

int addRow(expvec ev) {
 long    h, i, t;
 lvec    v;

 IntMatTime -= RunTime();

 /* Initialize Matrix[] and Heads[] on the first call. */
 if (Matrix == (lvec *)0) {
  EarlyStop = 0;
  Time = 0;
  if ((Matrix = (lvec*)malloc(200 * sizeof(lvec))) == (lvec *)0) {
   perror("addRow, Matrix ");
   exit(2);
  }
  if ((Heads = (long*)malloc(200 * sizeof(long))) == (long*)0) {
   perror("addRow, Heads ");
   exit(2);
  }
  NrCols = NrCenGens;
  MaximalEntry = ltom((expo)0);

  if (RawMatOutput) {
   char *file;
   int  c;

   c = Class + 1;
   file = (char *)calloc(12, sizeof(char));
   strcpy(file, "matrix.XXX");
   file[9] = c % 10 + '0';
   c /= 10;
   file[8] = c % 10 + '0';
   c /= 10;
   file[7] = c % 10 + '0';
   if ((RawMatFile = fopen(file, "w")) == NULL) {
    perror(file);
    exit(1);
   }
   fprintf(RawMatFile, "%ld\n", NrCols);
   fflush(RawMatFile);
   free(file);
  }
 }

 changedMatrix = 0;

 /* Check if the first NrPcGens entries in the exponent vector
** are zero. */

 for (i = 1; i <= NrPcGens; i++)
  if (ev[i] != 0) {
   printf("Warning, exponent vector is not a tail");
   printf(" at position %ld.\n", i);
   printEv(ev);
   printf("\n");
   break;
  }

 /* Find the head, i.e. the first non-zero entry, of ev. */
 for (h = 0, i = 1; i <= NrCols; i++)
  if (ev[NrPcGens + i] != 0) { h = i; break; }

 /* If ev is the null vector, free it and return. */
 if (h == 0) {
  Free(ev);
  IntMatTime += RunTime();
  return 0;
 }

 t = RunTime();

 /* Copy the last NrCenGens entries of ev and free it. */
 v = (lvec)malloc((NrCols + 1) * sizeof(large));
 if (v == (lvec)0) { perror("addRow(), v"); exit(2); }
 for (i = 1; i <= NrCols; i++)
  v[i] = ltom(ev[NrPcGens + i]);

 if (RawMatOutput) {
  for (i = 1; i <= NrCols; i++) {
   fprintf(RawMatFile, " "EXP_FORMAT, ev[NrPcGens + i]);
  }

  fprintf(RawMatFile, "\n");
  fflush(RawMatFile);
 }

 Free(ev);

 if ((v = vReduce(v, h)) != (lvec)0) {
  changedMatrix = 1;
  if (NrRows % 200 == 0) {
   Matrix = (lvec*)realloc(Matrix, (NrRows + 200) * sizeof(lvec));
   if (Matrix == (lvec*)0) {
    perror("addRow(), Matrix");
    exit(2);
   }
   Heads = (long*)realloc(Heads, (NrRows + 200) * sizeof(long));
   if (Heads == (long*)0) {
    perror("addRow(), Heads");
    exit(2);
   }
  }
  /* Insert ev such that Heads[] is in increasing order. */
  while (h <= NrCols && ISZERO(v[h])) h++;
  if (ISNEG(v[h])) vNeg(v, h);
  for (i = NrRows; i > 0; i--)
   if (Heads[i - 1] > h) {
    Matrix[i] = Matrix[i - 1];
    Heads[i] = Heads[i - 1];
   } else        break;
  /* Insert. */
  Matrix[ i ] = v;
  Heads[ i ] = h;
  NrRows++;
 }

 if (changedMatrix) lastReduce();


 /* Check if Matrix[] is the identity matrix. */
 if (NrRows == NrCenGens) {
  for (i = 0; i < NrRows; i++)
   /* Check if each leading entry is 1 */
   if (mpz_sizeinbase(Matrix[i][Heads[i]], 2) != 1) break;
  if (i == NrRows) EarlyStop = 1;
 }

 Time += RunTime() - t;
 if (EarlyStop)
  printf("# Integer matrix is the identity.\n");

 IntMatTime += RunTime();
 return changedMatrix;
}

/*
void printLarge(large l) {
mpz_out_str(stdout, 10, l);
printf("\n");
}
*/


Messung V0.5
C=94 H=99 G=96

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.