Changeset 5b2745 in git


Ignore:
Timestamp:
May 27, 2011, 6:39:50 PM (13 years ago)
Author:
Hans Schoenemann <hannes@…>
Branches:
(u'spielwiese', '2a584933abf2a2d3082034c7586d38bb6de1a30a')
Children:
7d1c995f987c51bad98f33e83e328a16ded060ec
Parents:
db83bf13b62d944de021f52de5ae04b7ffd0390e
Message:
fix unsigned/signed int usage

git-svn-id: file:///usr/local/Singular/svn/trunk@14252 2c84dea3-7e68-4137-9b89-c4e89433aadc
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Singular/minpoly.cc

    rdb83bf r5b2745  
    66
    77#include<cmath>
     8#include<Singular/mod2.h>
    89//#include<iomanip>
    910
     
    1213// TODO: avoid code copying, use subclassing instead!
    1314
    14 LinearDependencyMatrix::LinearDependencyMatrix(unsigned n, unsigned long p) {
    15     this->n = n;
    16     this->p = p;
    17 
    18     matrix = new unsigned long*[n];
    19     for (int i = 0; i < n; i++) {
    20         matrix[i] = new unsigned long[2*n + 1];
    21     }
    22     pivots = new unsigned[n];
    23     tmprow = new unsigned long[2*n + 1];
    24     rows = 0;
    25 }
    26 
    27 LinearDependencyMatrix::~LinearDependencyMatrix() {
    28     delete[] tmprow;
    29     delete[] pivots;
    30 
    31     for (int i = 0; i < n; i++) {
    32         delete[] (matrix[i]);
    33     }
    34     delete[] matrix;
    35 }
    36 
    37 void LinearDependencyMatrix::resetMatrix() {
    38     rows = 0;
    39 }
    40 
    41 int LinearDependencyMatrix::firstNonzeroEntry(unsigned long *row) {
    42     for (int i = 0; i < n; i++)
    43         if (row[i] != 0)
    44             return i;
    45 
    46     return -1;
    47 }
    48 
    49 void LinearDependencyMatrix::reduceTmpRow() {
    50     for (int i = 0; i < rows; i++) {
    51         unsigned piv = pivots[i];
    52         unsigned long x = tmprow[piv] % p;
    53         // if the corresponding entry in the row is zero, there is nothing to do
    54         if (x != 0) {
    55             // subtract tmprow[i] times the i-th row
    56             for (int j = piv; j < n + rows + 1; j++) {
    57                 unsigned long tmp = matrix[i][j]*x % p;
    58                 tmp = p - tmp;
    59                 tmprow[j] += tmp;
    60                 // We don't normalize here, so remember to do it after all reductions.
    61                 // tmprow[j] %= p;
    62             }
    63         }
    64     }
    65 
    66     // normalize the entries of tmprow.
    67     for (int i = 0; i < n + rows + 1; i++) {
    68         tmprow[i] %= p;
    69     }
    70 }
    71 
    72 
    73 void LinearDependencyMatrix::normalizeTmp(unsigned i) {
    74     unsigned long inv = modularInverse(tmprow[i], p);
    75     tmprow[i] = 1;
    76     for (int j = i+1; j < 2*n + 1; j++)
    77         tmprow[j] = (tmprow[j] * inv) % p;
    78 }
    79 
    80 bool LinearDependencyMatrix::findLinearDependency(unsigned long* newRow, unsigned long* dep) {
    81     // Copy newRow to tmprow (we need to add RHS)
    82     for (int i = 0; i < n; i++) {
    83         tmprow[i] = newRow[i];
    84         tmprow[n + i] = 0;
    85     }
    86     tmprow[2*n] = 0;
    87     tmprow[n + rows] = 1;
    88 
    89     reduceTmpRow();
    90 
    91     // Is tmprow reduced to zero? Then we have found a linear dependence.
    92     // Otherwise, we just add tmprow to the matrix.
    93     unsigned newpivot = firstNonzeroEntry(tmprow);
    94     if (newpivot == -1) {
    95         for (int i = 0; i <=n; i++) {
    96             dep[i] = tmprow[n+i];
    97         }
    98 
    99         return true;
    100     } else {
    101         normalizeTmp(newpivot);
    102 
    103         for (int i = 0; i < 2*n + 1; i++) {
    104             matrix[rows][i] = tmprow[i];
    105         }
    106 
    107         pivots[rows] = newpivot;
    108         rows++;
    109 
    110         return false;
    111     }
     15LinearDependencyMatrix::LinearDependencyMatrix (unsigned n, unsigned long p)
     16{
     17  this->n = n;
     18  this->p = p;
     19
     20  matrix = new unsigned long *[n];
     21  for(unsigned i = 0; i < n; i++)
     22  {
     23    matrix[i] = new unsigned long[2 * n + 1];
     24  }
     25  pivots = new unsigned[n];
     26  tmprow = new unsigned long[2 * n + 1];
     27  rows = 0;
     28}
     29
     30LinearDependencyMatrix::~LinearDependencyMatrix ()
     31{
     32  delete[]tmprow;
     33  delete[]pivots;
     34
     35  for(unsigned i = 0; i < n; i++)
     36  {
     37    delete[](matrix[i]);
     38  }
     39  delete[]matrix;
     40}
     41
     42void LinearDependencyMatrix::resetMatrix ()
     43{
     44  rows = 0;
     45}
     46
     47int LinearDependencyMatrix::firstNonzeroEntry (unsigned long *row)
     48{
     49  for(unsigned i = 0; i < n; i++)
     50    if(row[i] != 0)
     51      return i;
     52
     53  return -1;
     54}
     55
     56void LinearDependencyMatrix::reduceTmpRow ()
     57{
     58  for(unsigned i = 0; i < rows; i++)
     59  {
     60    unsigned piv = pivots[i];
     61    unsigned long x = tmprow[piv] % p;
     62    // if the corresponding entry in the row is zero, there is nothing to do
     63    if(x != 0)
     64    {
     65      // subtract tmprow[i] times the i-th row
     66      for(unsigned j = piv; j < n + rows + 1; j++)
     67      {
     68        unsigned long tmp = matrix[i][j] * x % p;
     69        tmp = p - tmp;
     70        tmprow[j] += tmp;
     71        // We don't normalize here, so remember to do it after all reductions.
     72        // tmprow[j] %= p;
     73      }
     74    }
     75  }
     76
     77  // normalize the entries of tmprow.
     78  for(unsigned i = 0; i < n + rows + 1; i++)
     79  {
     80    tmprow[i] %= p;
     81  }
     82}
     83
     84
     85void LinearDependencyMatrix::normalizeTmp (unsigned i)
     86{
     87  unsigned long inv = modularInverse (tmprow[i], p);
     88  tmprow[i] = 1;
     89  for(unsigned j = i + 1; j < 2 * n + 1; j++)
     90    tmprow[j] = (tmprow[j] * inv) % p;
     91}
     92
     93bool LinearDependencyMatrix::findLinearDependency (unsigned long *newRow,
     94                                                   unsigned long *dep)
     95{
     96  // Copy newRow to tmprow (we need to add RHS)
     97  for(unsigned i = 0; i < n; i++)
     98  {
     99    tmprow[i] = newRow[i];
     100    tmprow[n + i] = 0;
     101  }
     102  tmprow[2 * n] = 0;
     103  tmprow[n + rows] = 1;
     104
     105  reduceTmpRow ();
     106
     107  // Is tmprow reduced to zero? Then we have found a linear dependence.
     108  // Otherwise, we just add tmprow to the matrix.
     109  int newpivot = firstNonzeroEntry (tmprow);
     110  if(newpivot == -1)
     111  {
     112    for(unsigned i = 0; i <= n; i++)
     113    {
     114      dep[i] = tmprow[n + i];
     115    }
     116
     117    return true;
     118  }
     119  else
     120  {
     121    normalizeTmp (newpivot);
     122
     123    for(unsigned i = 0; i < 2 * n + 1; i++)
     124    {
     125      matrix[rows][i] = tmprow[i];
     126    }
     127
     128    pivots[rows] = newpivot;
     129    rows++;
     130
     131    return false;
     132  }
    112133}
    113134
    114135#if 0
    115 std::ostream& operator<<(std::ostream& out, const LinearDependencyMatrix& mat) {
    116     int width = ((int)log10(mat.p)) + 1;
    117 
    118     for (int i = 0; i < mat.rows; i++) {
    119         for (int j = 0; j < mat.n; j++) {
    120             out << std::setw(width) << mat.matrix[i][j] << " ";
    121         }
    122         out << "| ";
    123         for (int j = mat.n; j <= 2*mat.n; j++) {
    124             out << std::setw(width) << mat.matrix[i][j] << " ";
    125         }
    126         out << std::endl;
    127     }
    128     out << "-----" << std::endl;
    129     for (int j = 0; j < mat.n; j++) {
    130         out << std::setw(width) << mat.tmprow[j] << " ";
     136std::ostream & operator<< (std::ostream & out,
     137                           const LinearDependencyMatrix & mat)
     138{
     139  int width = ((int) log10 (mat.p)) + 1;
     140
     141  for(int i = 0; i < mat.rows; i++)
     142  {
     143    for(int j = 0; j < mat.n; j++)
     144    {
     145      out << std::setw (width) << mat.matrix[i][j] << " ";
    131146    }
    132147    out << "| ";
    133     for (int j = mat.n; j <= 2*mat.n; j++) {
    134         out << std::setw(width) << mat.tmprow[j] << " ";
     148    for(int j = mat.n; j <= 2 * mat.n; j++)
     149    {
     150      out << std::setw (width) << mat.matrix[i][j] << " ";
    135151    }
    136152    out << std::endl;
    137 
    138     return out;
     153  }
     154  out << "-----" << std::endl;
     155  for(int j = 0; j < mat.n; j++)
     156  {
     157    out << std::setw (width) << mat.tmprow[j] << " ";
     158  }
     159  out << "| ";
     160  for(int j = mat.n; j <= 2 * mat.n; j++)
     161  {
     162    out << std::setw (width) << mat.tmprow[j] << " ";
     163  }
     164  out << std::endl;
     165
     166  return out;
    139167}
    140168#endif
    141169
    142170
    143 NewVectorMatrix::NewVectorMatrix(unsigned n, unsigned long p) {
    144     this->n = n;
    145     this->p = p;
    146 
    147     matrix = new unsigned long*[n];
    148     for (int i = 0; i < n; i++) {
    149         matrix[i] = new unsigned long[n];
    150     }
    151 
    152     pivots = new unsigned[n];
    153     rows = 0;
    154 }
    155 
    156 NewVectorMatrix::~NewVectorMatrix() {
    157     delete pivots;
    158 
    159     for (int i = 0; i < n; i++) {
    160         delete[] matrix[i];
    161     }
    162     delete matrix;
    163 }
    164 
    165 int NewVectorMatrix::firstNonzeroEntry(unsigned long *row) {
    166     for (int i = 0; i < n; i++)
    167         if (row[i] != 0)
    168             return i;
    169 
    170     return -1;
     171NewVectorMatrix::NewVectorMatrix (unsigned n, unsigned long p)
     172{
     173  this->n = n;
     174  this->p = p;
     175
     176  matrix = new unsigned long *[n];
     177  for(unsigned i = 0; i < n; i++)
     178  {
     179    matrix[i] = new unsigned long[n];
     180  }
     181
     182  pivots = new unsigned[n];
     183  rows = 0;
     184}
     185
     186NewVectorMatrix::~NewVectorMatrix ()
     187{
     188  delete pivots;
     189
     190  for(unsigned i = 0; i < n; i++)
     191  {
     192    delete[]matrix[i];
     193  }
     194  delete matrix;
     195}
     196
     197int NewVectorMatrix::firstNonzeroEntry (unsigned long *row)
     198{
     199  for(unsigned i = 0; i < n; i++)
     200    if(row[i] != 0)
     201      return i;
     202
     203  return -1;
    171204}
    172205
     
    182215//}
    183216//
    184 void NewVectorMatrix::normalizeRow(unsigned long *row, unsigned i) {
    185     unsigned long inv = modularInverse(row[i], p);
    186     row[i] = 1;
    187 
    188     for (int j = i+1; j < n; j++) {
    189         row[j] = (row[j] * inv) % p;
    190     }
    191 }
    192 
    193 void NewVectorMatrix::insertRow(unsigned long* row) {
    194     for (int i = 0; i < rows; i++) {
    195         unsigned piv = pivots[i];
    196         unsigned long x = row[piv] % p;
    197         // if the corresponding entry in the row is zero, there is nothing to do
    198         if (x != 0) {
    199             // subtract row[i] times the i-th row
    200             for (int j = piv; j < n; j++) {
    201                 unsigned long tmp = matrix[i][j]*x % p;
    202                 tmp = p - tmp;
    203                 row[j] += tmp;
    204                 // We don't normalize here, so remember to do it after all reductions.
    205                 // row[j] %= p;
    206             }
     217void NewVectorMatrix::normalizeRow (unsigned long *row, unsigned i)
     218{
     219  unsigned long inv = modularInverse (row[i], p);
     220  row[i] = 1;
     221
     222  for(unsigned j = i + 1; j < n; j++)
     223  {
     224    row[j] = (row[j] * inv) % p;
     225  }
     226}
     227
     228void NewVectorMatrix::insertRow (unsigned long *row)
     229{
     230  unsigned i;
     231  for(i = 0; i < rows; i++)
     232  {
     233    unsigned piv = pivots[i];
     234    unsigned long x = row[piv] % p;
     235    // if the corresponding entry in the row is zero, there is nothing to do
     236    if(x != 0)
     237    {
     238      // subtract row[i] times the i-th row
     239      for(int j = piv; j < (int)n; j++)
     240      {
     241        unsigned long tmp = matrix[i][j] * x % p;
     242        tmp = p - tmp;
     243        row[j] += tmp;
     244        // We don't normalize here, so remember to do it after all reductions.
     245        // row[j] %= p;
     246      }
     247    }
     248  }
     249
     250  // normalize the entries of row.
     251  for(i = 0; i < n + rows + 1; i++)
     252  {
     253    row[i] %= p;
     254  }
     255
     256  int piv = firstNonzeroEntry (row);
     257
     258  if(piv != -1)
     259  {
     260    // normalize and insert row into the matrix
     261    normalizeRow (row, piv);
     262    for(i = 0; i < n; i++)
     263    {
     264      matrix[rows][i] = row[i];
     265    }
     266
     267    pivots[rows] = piv;
     268    rows++;
     269  }
     270}
     271
     272
     273void NewVectorMatrix::insertMatrix (LinearDependencyMatrix & mat)
     274{
     275  // The matrix in LinearDependencyMatrix is already in reduced form.
     276  // Thus, if the current matrix is empty, we can simply copy the other matrix.
     277  if(rows == 0)
     278  {
     279    for(unsigned i = 0; i < mat.rows; i++)
     280    {
     281      for(unsigned j = 0; j < n; j++)
     282      {
     283        matrix[i][j] = mat.matrix[i][j];
     284
     285        rows = mat.rows;
     286        for(unsigned ii = 0; ii < rows; ii++)
     287        {
     288          pivots[ii] = mat.pivots[ii];
    207289        }
    208     }
    209 
    210     // normalize the entries of row.
    211     for (int i = 0; i < n + rows + 1; i++) {
    212         row[i] %= p;
    213     }
    214 
    215     unsigned piv = firstNonzeroEntry(row);
    216 
    217     if (piv != -1) {
    218         // normalize and insert row into the matrix
    219         normalizeRow(row, piv);
    220         for (int i = 0; i < n; i++) {
    221             matrix[rows][i] = row[i];
    222         }
    223 
    224         pivots[rows] = piv;
    225         rows++;
    226     }
    227 }
    228 
    229 
    230 void NewVectorMatrix::insertMatrix(LinearDependencyMatrix& mat) {
    231     // The matrix in LinearDependencyMatrix is already in reduced form.
    232     // Thus, if the current matrix is empty, we can simply copy the other matrix.
    233     if (rows == 0) {
    234         for (int i = 0; i < mat.rows; i++) {
    235             for (int j = 0; j < n; j++) {
    236                 matrix[i][j] = mat.matrix[i][j];
    237 
    238                 rows = mat.rows;
    239                 for (int i = 0; i < rows; i++) {
    240                     pivots[i] = mat.pivots[i];
    241                 }
    242             }
    243         }
    244     } else {
    245         for (int i = 0; i < mat.rows; i++) {
    246             insertRow(mat.matrix[i]);
    247         }
    248     }
    249 }
    250 
    251 int NewVectorMatrix::findSmallestNonpivot() {
    252     // This method isn't very efficient, but it is called at most a few times, so efficiency is not important.
    253     if (rows == n)
    254         return -1;
    255 
    256     for (int i = 0; i < n; i++) {
    257         bool isPivot = false;
    258         for (int j = 0; j < rows; j++) {
    259             if (pivots[j] == i) {
    260                 isPivot = true;
    261                 break;
    262             }
    263         }
    264 
    265         if (!isPivot) {
    266             return i;
    267         }
    268     }
    269 }
    270 
    271 
    272 void vectorMatrixMult(unsigned long* vec, unsigned long **mat, unsigned long* result, unsigned n, unsigned long p) {
    273     unsigned long tmp;
    274     for (int i = 0; i < n; i++) {
    275         result[i] = 0;
    276         for (int j = 0; j < n; j++) {
    277             tmp = vec[j]*mat[j][i] % p;
    278             result[i] += tmp;
    279         }
    280         // We can afford to reduce mod p only after all additions, since p < 2^31, but an unsigned long can store 2^64.
    281         // Thus the only possibility for an overflow would occurr for matrices with about 2^31 rows.
    282         result[i] %= p;
    283     }
     290      }
     291    }
     292  }
     293  else
     294  {
     295    for(unsigned i = 0; i < mat.rows; i++)
     296    {
     297      insertRow (mat.matrix[i]);
     298    }
     299  }
     300}
     301
     302int NewVectorMatrix::findSmallestNonpivot ()
     303{
     304  // This method isn't very efficient, but it is called at most a few times, so efficiency is not important.
     305  if(rows == n)
     306    return -1;
     307
     308  for(unsigned i = 0; i < n; i++)
     309  {
     310    bool isPivot = false;
     311    for(unsigned j = 0; j < rows; j++)
     312    {
     313      if(pivots[j] == i)
     314      {
     315        isPivot = true;
     316        break;
     317      }
     318    }
     319
     320    if(!isPivot)
     321    {
     322      return i;
     323    }
     324  }
     325  assume(0);
     326  return -1; // to make the compiler happy
     327}
     328
     329
     330void vectorMatrixMult (unsigned long *vec, unsigned long **mat,
     331                       unsigned long *result, unsigned n, unsigned long p)
     332{
     333  unsigned long tmp;
     334  for(unsigned i = 0; i < n; i++)
     335  {
     336    result[i] = 0;
     337    for(unsigned j = 0; j < n; j++)
     338    {
     339      tmp = vec[j] * mat[j][i] % p;
     340      result[i] += tmp;
     341    }
     342    // We can afford to reduce mod p only after all additions, since p < 2^31, but an unsigned long can store 2^64.
     343    // Thus the only possibility for an overflow would occurr for matrices with about 2^31 rows.
     344    result[i] %= p;
     345  }
    284346}
    285347
    286348#if 0
    287 void printVec(unsigned long* vec, int n) {
    288     for (int i = 0; i < n; i++) {
    289         std::cout << vec[i] << ", ";
    290     }
    291 
    292     std::cout << std::endl;
     349void printVec (unsigned long *vec, int n)
     350{
     351  for(int i = 0; i < n; i++)
     352  {
     353    std::cout << vec[i] << ", ";
     354  }
     355
     356  std::cout << std::endl;
    293357}
    294358#endif
    295359
    296360
    297 unsigned long* computeMinimalPolynomial(unsigned long** matrix, unsigned n, unsigned long p) {
    298     LinearDependencyMatrix lindepmat(n, p);
    299     NewVectorMatrix newvectormat(n, p);
    300 
    301     unsigned long* result = new unsigned long[n+1];
    302     unsigned long* mpvec = new unsigned long[n+1];
    303     unsigned long* tmp = new unsigned long[n+1];
    304 
    305     // initialize result = 1
    306     for (int i = 0; i <= n; i++) {
    307         result[i] = 0;
    308     }
    309     result[0] = 1;
    310 
    311     int degresult = 0;
    312 
    313 
    314     int i = 0;
    315 
    316     unsigned long* vec = new unsigned long[n];
    317     unsigned long* vecnew = new unsigned long[n];
    318 
    319     while (i != -1) {
    320         for (int j = 0; j < n; j++) {
    321             vec[j] = 0;
    322         }
    323         vec[i] = 1;
    324 
    325         lindepmat.resetMatrix();
    326 
    327         while (true) {
    328             bool ld = lindepmat.findLinearDependency(vec, mpvec);
    329 
    330             if (ld) {
    331                 break;
    332             }
    333 
    334             vectorMatrixMult(vec, matrix, vecnew, n, p);
    335             unsigned long* swap = vec;
    336             vec = vecnew;
    337             vecnew = swap;
    338         }
    339 
    340 
    341         unsigned degmpvec = n;
    342         while (mpvec[degmpvec] == 0) {
    343             degmpvec--;
    344         }
    345 
    346         // if the dimension is already maximal, i.e., the minimal polynomial of vec has the highest possible degree,
    347         // then we are done.
    348         if (degmpvec == n) {
    349             unsigned long* swap = result;
    350             result = mpvec;
    351             mpvec = swap;
    352             i = -1;
    353         } else {
    354             // otherwise, we have to compute the lcm of mpvec and prior result
    355 
    356             // tmp = zeropol
    357             for (int j = 0; j <= n; j++) {
    358                 tmp[j] = 0;
    359             }
    360             degresult  = lcm(tmp, result, mpvec, p, degresult, degmpvec);
    361             unsigned long* swap = result;
    362             result = tmp;
    363             tmp = swap;
    364 
    365             if (degresult == n) {
    366                 // minimal polynomial has highest possible degree, so we are done.
    367                 i = -1;
    368             } else {
    369                 newvectormat.insertMatrix(lindepmat);
    370                 i = newvectormat.findSmallestNonpivot();
    371             }
    372         }
    373     }
    374 
    375     // TODO: take lcms of the different monomials!
    376 
    377     delete[] vecnew;
    378     delete[] vec;
    379     delete[] tmp;
    380     delete[] mpvec;
    381 
    382     return result;
    383 }
    384 
    385 
    386 void rem(unsigned long* a, unsigned long* q, unsigned long p, int & dega, int degq) {
    387     while (degq <= dega) {
    388         unsigned d = dega - degq;
    389         long factor = a[dega]*modularInverse(q[degq], p) % p;
    390         for (int i = degq; i >= 0; i--) {
    391             long tmp = p - (factor*q[i] % p);
    392             a[d + i] += tmp;
    393             a[d + i] %= p;
    394         }
    395 
    396         while (a[dega] == 0 && dega >= 0) {
    397             dega--;
    398         }
    399     }
    400 }
    401 
    402 
    403 void quo(unsigned long* a, unsigned long* q, unsigned long p, int & dega, int degq) {
    404     unsigned degres = dega - degq;
    405     unsigned long* result = new unsigned long[degres + 1];
    406 
    407     while (degq <= dega) {
    408         unsigned d = dega - degq;
    409         long inv = modularInverse(q[degq], p);
    410         result[d] = a[dega]*inv % p;
    411         for (int i = degq; i >= 0; i--) {
    412             long tmp = p - (result[d]*q[i] % p);
    413             a[d + i] += tmp;
    414             a[d + i] %= p;
    415         }
    416 
    417         while (a[dega] == 0 && dega >= 0) {
    418             dega--;
    419         }
    420     }
    421 
    422     // copy result into a
    423     for (int i = 0; i <= degres; i++) {
    424         a[i] = result[i];
    425     }
    426     // set all following entries of a to zero
    427     for (int i = degres + 1; i <= degq + degres; i++) {
    428         a[i] = 0;
    429     }
    430 
    431     dega = degres;
    432 
    433     delete[] result;
    434 }
    435 
    436 
    437 void mult(unsigned long* result, unsigned long* a, unsigned long* b, unsigned long p, int dega, int degb) {
    438     // NOTE: we assume that every entry in result is preinitialized to zero!
    439 
    440     for (int i = 0; i <= dega; i++) {
    441         for (int j = 0; j <= degb; j++) {
    442             result[i + j] += (a[i]*b[j] % p);
    443             result[i + j] %= p;
    444         }
    445     }
    446 }
    447 
    448 
    449 int gcd(unsigned long* g, unsigned long* a, unsigned long* b, unsigned long p, int dega, int degb) {
    450     unsigned long* tmp1 = new unsigned long[dega + 1];
    451     unsigned long* tmp2 = new unsigned long[degb + 1];
    452     for (int i = 0; i <= dega; i++) {
    453         tmp1[i] = a[i];
    454     }
    455     for (int i = 0; i <= degb; i++) {
    456         tmp2[i] = b[i];
    457     }
    458     int degtmp1 = dega;
    459     int degtmp2 = degb;
    460 
    461     unsigned long* swappol;
    462     int swapdeg;
    463 
    464     while (degtmp2 >= 0) {
    465         rem(tmp1, tmp2, p, degtmp1, degtmp2);
    466         swappol = tmp1;
    467         tmp1 = tmp2;
    468         tmp2 = swappol;
    469 
    470         swapdeg = degtmp1;
    471         degtmp1 = degtmp2;
    472         degtmp2 = swapdeg;
    473     }
    474 
    475     for (int i = 0; i <= degtmp1; i++) {
    476         g[i] = tmp1[i];
    477     }
    478 
    479     delete[] tmp1;
    480     delete[] tmp2;
    481 
    482     return degtmp1;
    483 }
    484 
    485 
    486 int lcm(unsigned long* l, unsigned long* a, unsigned long* b, unsigned long p, int dega, int degb) {
    487     unsigned long* g = new unsigned long[dega + 1];
    488     // initialize entries of g to zero
    489     for (int i = 0; i <= dega; i++) {
    490         g[i] = 0;
    491     }
    492 
    493     int degg = gcd(g, a, b, p, dega, degb);
    494 
    495     if (degg > 0) {
    496         // non-trivial gcd, so compute a = (a/g)
    497         quo(a, g, p, dega, degg);
    498     }
    499     mult(l, a, b, p, dega, degb);
    500 
    501     // normalize
    502     if (l[dega + degb + 1] != 1) {
    503         unsigned long inv = modularInverse(l[dega + degb], p);
    504         for (int i = 0; i <= dega + degb; i++) {
    505             l[i] *= inv;
    506             l[i] %= p;
    507         }
    508     }
    509 
    510     return dega + degb;
     361unsigned long *computeMinimalPolynomial (unsigned long **matrix, unsigned n,
     362                                         unsigned long p)
     363{
     364  LinearDependencyMatrix lindepmat (n, p);
     365  NewVectorMatrix newvectormat (n, p);
     366
     367  unsigned long *result = new unsigned long[n + 1];
     368  unsigned long *mpvec = new unsigned long[n + 1];
     369  unsigned long *tmp = new unsigned long[n + 1];
     370
     371  // initialize result = 1
     372  for(unsigned i = 0; i <= n; i++)
     373  {
     374    result[i] = 0;
     375  }
     376  result[0] = 1;
     377
     378  int degresult = 0;
     379
     380
     381  int i = 0;
     382
     383  unsigned long *vec = new unsigned long[n];
     384  unsigned long *vecnew = new unsigned long[n];
     385
     386  while(i != -1)
     387  {
     388    for(unsigned j = 0; j < n; j++)
     389    {
     390      vec[j] = 0;
     391    }
     392    vec[i] = 1;
     393
     394    lindepmat.resetMatrix ();
     395
     396    while(true)
     397    {
     398      bool ld = lindepmat.findLinearDependency (vec, mpvec);
     399
     400      if(ld)
     401      {
     402        break;
     403      }
     404
     405      vectorMatrixMult (vec, matrix, vecnew, n, p);
     406      unsigned long *swap = vec;
     407      vec = vecnew;
     408      vecnew = swap;
     409    }
     410
     411
     412    unsigned degmpvec = n;
     413    while(mpvec[degmpvec] == 0)
     414    {
     415      degmpvec--;
     416    }
     417
     418    // if the dimension is already maximal, i.e., the minimal polynomial of vec has the highest possible degree,
     419    // then we are done.
     420    if(degmpvec == n)
     421    {
     422      unsigned long *swap = result;
     423      result = mpvec;
     424      mpvec = swap;
     425      i = -1;
     426    }
     427    else
     428    {
     429      // otherwise, we have to compute the lcm of mpvec and prior result
     430
     431      // tmp = zeropol
     432      for(unsigned j = 0; j <= n; j++)
     433      {
     434        tmp[j] = 0;
     435      }
     436      degresult = lcm (tmp, result, mpvec, p, degresult, degmpvec);
     437      unsigned long *swap = result;
     438      result = tmp;
     439      tmp = swap;
     440
     441      if(degresult == n)
     442      {
     443        // minimal polynomial has highest possible degree, so we are done.
     444        i = -1;
     445      }
     446      else
     447      {
     448        newvectormat.insertMatrix (lindepmat);
     449        i = newvectormat.findSmallestNonpivot ();
     450      }
     451    }
     452  }
     453
     454  // TODO: take lcms of the different monomials!
     455
     456  delete[]vecnew;
     457  delete[]vec;
     458  delete[]tmp;
     459  delete[]mpvec;
     460
     461  return result;
     462}
     463
     464
     465void rem (unsigned long *a, unsigned long *q, unsigned long p, int &dega,
     466          int degq)
     467{
     468  while(degq <= dega)
     469  {
     470    unsigned d = dega - degq;
     471    long factor = a[dega] * modularInverse (q[degq], p) % p;
     472    for(int i = degq; i >= 0; i--)
     473    {
     474      long tmp = p - (factor * q[i] % p);
     475      a[d + i] += tmp;
     476      a[d + i] %= p;
     477    }
     478
     479    while(a[dega] == 0 && dega >= 0)
     480    {
     481      dega--;
     482    }
     483  }
     484}
     485
     486
     487void quo (unsigned long *a, unsigned long *q, unsigned long p, int &dega,
     488          int degq)
     489{
     490  unsigned degres = dega - degq;
     491  unsigned long *result = new unsigned long[degres + 1];
     492  unsigned i;
     493
     494  while(degq <= dega)
     495  {
     496    unsigned d = dega - degq;
     497    long inv = modularInverse (q[degq], p);
     498    result[d] = a[dega] * inv % p;
     499    for(i = degq; i >= 0; i--)
     500    {
     501      long tmp = p - (result[d] * q[i] % p);
     502      a[d + i] += tmp;
     503      a[d + i] %= p;
     504    }
     505
     506    while(a[dega] == 0 && dega >= 0)
     507    {
     508      dega--;
     509    }
     510  }
     511
     512  // copy result into a
     513  for(i = 0; i <= degres; i++)
     514  {
     515    a[i] = result[i];
     516  }
     517  // set all following entries of a to zero
     518  for(i = degres + 1; i <= degq + degres; i++)
     519  {
     520    a[i] = 0;
     521  }
     522
     523  dega = degres;
     524
     525  delete[]result;
     526}
     527
     528
     529void mult (unsigned long *result, unsigned long *a, unsigned long *b,
     530           unsigned long p, int dega, int degb)
     531{
     532  // NOTE: we assume that every entry in result is preinitialized to zero!
     533
     534  for(int i = 0; i <= dega; i++)
     535  {
     536    for(int j = 0; j <= degb; j++)
     537    {
     538      result[i + j] += (a[i] * b[j] % p);
     539      result[i + j] %= p;
     540    }
     541  }
     542}
     543
     544
     545int gcd (unsigned long *g, unsigned long *a, unsigned long *b,
     546         unsigned long p, int dega, int degb)
     547{
     548  unsigned long *tmp1 = new unsigned long[dega + 1];
     549  unsigned long *tmp2 = new unsigned long[degb + 1];
     550  for(int i = 0; i <= dega; i++)
     551  {
     552    tmp1[i] = a[i];
     553  }
     554  for(int i = 0; i <= degb; i++)
     555  {
     556    tmp2[i] = b[i];
     557  }
     558  int degtmp1 = dega;
     559  int degtmp2 = degb;
     560
     561  unsigned long *swappol;
     562  int swapdeg;
     563
     564  while(degtmp2 >= 0)
     565  {
     566    rem (tmp1, tmp2, p, degtmp1, degtmp2);
     567    swappol = tmp1;
     568    tmp1 = tmp2;
     569    tmp2 = swappol;
     570
     571    swapdeg = degtmp1;
     572    degtmp1 = degtmp2;
     573    degtmp2 = swapdeg;
     574  }
     575
     576  for(int i = 0; i <= degtmp1; i++)
     577  {
     578    g[i] = tmp1[i];
     579  }
     580
     581  delete[]tmp1;
     582  delete[]tmp2;
     583
     584  return degtmp1;
     585}
     586
     587
     588int lcm (unsigned long *l, unsigned long *a, unsigned long *b,
     589         unsigned long p, int dega, int degb)
     590{
     591  unsigned long *g = new unsigned long[dega + 1];
     592  // initialize entries of g to zero
     593  for(int i = 0; i <= dega; i++)
     594  {
     595    g[i] = 0;
     596  }
     597
     598  int degg = gcd (g, a, b, p, dega, degb);
     599
     600  if(degg > 0)
     601  {
     602    // non-trivial gcd, so compute a = (a/g)
     603    quo (a, g, p, dega, degg);
     604  }
     605  mult (l, a, b, p, dega, degb);
     606
     607  // normalize
     608  if(l[dega + degb + 1] != 1)
     609  {
     610    unsigned long inv = modularInverse (l[dega + degb], p);
     611    for(int i = 0; i <= dega + degb; i++)
     612    {
     613      l[i] *= inv;
     614      l[i] %= p;
     615    }
     616  }
     617
     618  return dega + degb;
    511619}
    512620
    513621
    514622// compute x^(-1) mod p
    515 long modularInverse(long x, long p) {
    516     long u1 = 1;
    517     long u2 = 0;
    518     long u3 = x;
    519     long v1 = 0;
    520     long v2 = 1;
    521     long v3 = p;
    522 
    523     long q, t1, t2, t3;
    524     while (v3 != 0) {
    525         q = u3 / v3;
    526         t1 = u1 - q * v1;
    527         t2 = u2 - q * v2;
    528         t3 = u3 - q * v3;
    529         u1 = v1;
    530         u2 = v2;
    531         u3 = v3;
    532         v1 = t1;
    533         v2 = t2;
    534         v3 = t3;
    535     }
    536 
    537     if (u1 < 0) {
    538         u1 += p;
    539     }
    540 
    541     return u1;
    542 }
     623long modularInverse (long x, long p)
     624{
     625  long u1 = 1;
     626  long u2 = 0;
     627  long u3 = x;
     628  long v1 = 0;
     629  long v2 = 1;
     630  long v3 = p;
     631
     632  long q, t1, t2, t3;
     633  while(v3 != 0)
     634  {
     635    q = u3 / v3;
     636    t1 = u1 - q * v1;
     637    t2 = u2 - q * v2;
     638    t3 = u3 - q * v3;
     639    u1 = v1;
     640    u2 = v2;
     641    u3 = v3;
     642    v1 = t1;
     643    v2 = t2;
     644    v3 = t3;
     645  }
     646
     647  if(u1 < 0)
     648  {
     649    u1 += p;
     650  }
     651
     652  return u1;
     653}
     654
    543655/*
    544656int main() {
     
    744856}
    745857*/
    746 
Note: See TracChangeset for help on using the changeset viewer.