Changeset f613a24 in git


Ignore:
Timestamp:
Jun 13, 2012, 9:31:39 AM (12 years ago)
Author:
Hans Schoenemann <hannes@…>
Branches:
(u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
Children:
02d8afb153e54b4dca7a1c7e782b73b7df40b090
Parents:
ae1e243d742c878b2d7dcb278a6785540ef2b894
Message:
fix: Singular/minpoly.{cc|h}

bugfixes and optimizations
on behalf of Sebastian Jambor
version sent in via e-mail on June 6, 2012, 17:00:31 MESZ for master
Location:
Singular
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • Singular/minpoly.cc

    rae1e24 rf613a24  
    1 /***********************************************
    2  * Copyright (C) 2011 Sebastian Jambor         *
    3  * sebastian@momo.math.rwth-aachen.de          *
    4  ***********************************************/
     1/*************************************************
     2 * Author: Sebastian Jambor, 2011                *
     3 * GPL (e-mail from June 6, 2012, 17:00:31 MESZ) *
     4 * sebastian@momo.math.rwth-aachen.de            *
     5 ************************************************/
    56
    67
     
    89#include "config.h"
    910#include<kernel/mod2.h>
     11
    1012//#include<iomanip>
    1113
     
    6769      for(int j = piv; j < n + rows + 1; j++)
    6870      {
    69         unsigned long tmp = multMod (matrix[i][j], x, p);
    70         tmp = p - tmp;
    71         tmprow[j] += tmp;
    72         tmprow[j] %= p;
     71        if (matrix[i][j] != 0)
     72        {
     73          unsigned long tmp = multMod (matrix[i][j], x, p);
     74          tmp = p - tmp;
     75          tmprow[j] += tmp;
     76          if (tmprow[j] >= p)
     77          {
     78            tmprow[j] -= p;
     79          }
     80        }
    7381      }
    7482    }
     
    182190
    183191  pivots = new unsigned[n];
     192
     193  nonPivots = new unsigned[n];
     194
     195  for (int i = 0; i < n; i++)
     196  {
     197     nonPivots[i] = i;
     198  }
     199
    184200  rows = 0;
    185201}
     
    187203NewVectorMatrix::~NewVectorMatrix ()
    188204{
     205  delete nonPivots;
    189206  delete pivots;
    190207
     
    226243    {
    227244      // subtract row[i] times the i-th row
    228       for(int j = piv; j < n; j++)
    229       {
    230         unsigned long tmp = multMod (matrix[i][j], x, p);
    231         tmp = p - tmp;
    232         row[j] += tmp;
    233         row[j] %= p;
     245      // only the non-pivot entries have to be considered
     246      // (and also the first entry)
     247      row[piv] = 0;
     248
     249      int smallestNonPivIndex = 0;
     250      while (nonPivots[smallestNonPivIndex] < piv)
     251      {
     252        smallestNonPivIndex++;
     253      }
     254
     255      for (int j = smallestNonPivIndex; j < n-rows; j++)
     256      {
     257        unsigned ind = nonPivots[j];
     258        if (matrix[i][ind] != 0)
     259        {
     260          unsigned long tmp = multMod (matrix[i][ind], x, p);
     261          tmp = p - tmp;
     262          row[ind] += tmp;
     263          if (row[ind] >= p)
     264          {
     265            row[ind] -= p;
     266          }
     267        }
    234268      }
    235269    }
     
    240274  if(piv != -1)
    241275  {
    242     // normalize and insert row into the matrix
     276    // Normalize and insert row into the matrix.
     277    // Then reduce upwards.
    243278    normalizeRow (row, piv);
    244279    for(int i = 0; i < n; i++)
     
    247282    }
    248283
     284
     285    for (int i = 0; i < rows; i++)
     286    {
     287      unsigned x = matrix[i][piv];
     288      // if the corresponding entry in the matrix is zero,
     289      // there is nothing to do
     290      if (x != 0)
     291      {
     292        for (int j = piv; j < n; j++)
     293        {
     294          if (row[j] != 0)
     295          {
     296            unsigned long tmp = multMod(row[j], x, p);
     297            tmp = p - tmp;
     298            matrix[i][j] += tmp;
     299            if (matrix[i][j] >= p)
     300            {
     301              matrix[i][j] -= p;
     302            }
     303          }
     304        }
     305      }
     306    }
     307
    249308    pivots[rows] = piv;
     309
     310    // update nonPivots
     311    for (int i = 0; i < n-rows; i++)
     312    {
     313      if (nonPivots[i] == piv)
     314      {
     315        // shift everything one position to the left
     316        for (int j = i; j < n-rows-1; j++)
     317        {
     318          nonPivots[j] = nonPivots[j+1];
     319        }
     320
     321        break;
     322      }
     323    }
     324
    250325    rows++;
    251326  }
     
    255330void NewVectorMatrix::insertMatrix (LinearDependencyMatrix & mat)
    256331{
    257   // The matrix in LinearDependencyMatrix is already in reduced form.
    258   // Thus, if the current matrix is empty, we can simply copy the other matrix.
    259   if(rows == 0)
    260   {
    261     for(int i = 0; i < mat.rows; i++)
    262     {
    263       for(int j = 0; j < n; j++)
    264       {
    265         matrix[i][j] = mat.matrix[i][j];
    266 
    267         rows = mat.rows;
    268         for(int i = 0; i < rows; i++)
    269         {
    270           pivots[i] = mat.pivots[i];
    271         }
    272       }
    273     }
    274   }
    275   else
    276   {
    277     for(int i = 0; i < mat.rows; i++)
    278     {
    279       insertRow (mat.matrix[i]);
    280     }
     332  for(int i = 0; i < mat.rows; i++)
     333  {
     334    insertRow (mat.matrix[i]);
    281335  }
    282336}
    283337
    284338int NewVectorMatrix::findSmallestNonpivot ()
     339{
     340  // This method isn't very efficient, but it is called at most a few times,
     341  // so efficiency is not important.
     342  if(rows == n)
     343    return -1;
     344
     345  for(int i = 0; i < n; i++)
     346  {
     347    bool isPivot = false;
     348    for(int j = 0; j < rows; j++)
     349    {
     350      if(pivots[j] == i)
     351      {
     352        isPivot = true;
     353        break;
     354      }
     355    }
     356
     357    if(!isPivot)
     358    {
     359      return i;
     360    }
     361  }
     362}
     363
     364int NewVectorMatrix::findLargestNonpivot ()
    285365{
    286366  // This method isn't very efficient, but it is called at most a few times, so efficiency is not important.
     
    288368    return -1;
    289369
    290   for(int i = 0; i < n; i++)
     370  for(int i = n-1; i >= 0; i--)
    291371  {
    292372    bool isPivot = false;
     
    309389
    310390void vectorMatrixMult (unsigned long *vec, unsigned long **mat,
     391                       unsigned **nonzeroIndices, unsigned *nonzeroCounts,
    311392                       unsigned long *result, unsigned n, unsigned long p)
    312393{
    313394  unsigned long tmp;
     395
    314396  for(int i = 0; i < n; i++)
    315397  {
    316398    result[i] = 0;
    317     for(int j = 0; j < n; j++)
    318     {
    319       tmp = multMod (vec[j], mat[j][i], p);
     399    for(int j = 0; j < nonzeroCounts[i]; j++)
     400    {
     401      tmp = multMod (vec[nonzeroIndices[i][j]], mat[nonzeroIndices[i][j]][i], p);
    320402      result[i] += tmp;
    321       result[i] %= p;
     403      if (result[i] >= p)
     404      {
     405        result[i] -= p;
     406      }
    322407    }
    323408  }
     
    358443
    359444
    360   int i = 0;
     445  // Store the indices where the matrix has non-zero entries.
     446  // This has a huge impact on spares matrices.
     447  unsigned* nonzeroCounts = new unsigned[n];
     448  unsigned** nonzeroIndices = new unsigned*[n];
     449  for (int i = 0; i < n; i++)
     450  {
     451    nonzeroIndices[i] = new unsigned[n];
     452    nonzeroCounts[i] = 0;
     453    for (int j = 0; j < n; j++)
     454    {
     455      if (matrix[j][i] != 0)
     456      {
     457        nonzeroIndices[i][nonzeroCounts[i]] = j;
     458        nonzeroCounts[i]++;
     459      }
     460    }
     461  }
     462
     463  int i = n-1;
    361464
    362465  unsigned long *vec = new unsigned long[n];
    363466  unsigned long *vecnew = new unsigned long[n];
    364467
     468  unsigned loopsEven = true;
    365469  while(i != -1)
    366470  {
     
    382486      }
    383487
    384       vectorMatrixMult (vec, matrix, vecnew, n, p);
     488      vectorMatrixMult (vec, matrix, nonzeroIndices, nonzeroCounts, vecnew, n, p);
    385489      unsigned long *swap = vec;
    386490      vec = vecnew;
     
    426530      {
    427531        newvectormat.insertMatrix (lindepmat);
    428         i = newvectormat.findSmallestNonpivot ();
    429       }
    430     }
    431   }
    432 
    433   // TODO: take lcms of the different monomials!
     532
     533        // choose new unit vector from the front or the end, alternating
     534        // for each round. If the matrix is the companion matrix for x^n,
     535        // then taking vectors from the end is best. If it is the transpose,
     536        // taking vectors from the front is best.
     537        // This tries to take the middle way
     538        if (loopsEven)
     539        {
     540          i = newvectormat.findSmallestNonpivot ();
     541        }
     542        else
     543        {
     544          i = newvectormat.findLargestNonpivot ();
     545        }
     546      }
     547    }
     548
     549    loopsEven = !loopsEven;
     550  }
     551
     552  for (int i = 0; i < n; i++)
     553  {
     554    delete[] nonzeroIndices[i];
     555  }
     556  delete[] nonzeroIndices;
     557  delete[] nonzeroCounts;
     558
    434559
    435560  delete[]vecnew;
     
    453578      long tmp = p - multMod (factor, q[i], p);
    454579      a[d + i] += tmp;
    455       a[d + i] %= p;
    456     }
    457 
    458     while(a[dega] == 0 && dega >= 0)
     580      if (a[d + i] >= p)
     581      {
     582        a[d + i] -= p;
     583      }
     584    }
     585
     586    while(dega >= 0 && a[dega] == 0)
    459587    {
    460588      dega--;
     
    470598  unsigned long *result = new unsigned long[degres + 1];
    471599
     600  // initialize to zero
     601  for (int i = 0; i <= degres; i++)
     602  {
     603    result[i] = 0;
     604  }
     605
    472606  while(degq <= dega)
    473607  {
    474608    unsigned d = dega - degq;
    475     long inv = modularInverse (q[degq], p);
     609    unsigned long inv = modularInverse (q[degq], p);
    476610    result[d] = multMod (a[dega], inv, p);
    477611    for(int i = degq; i >= 0; i--)
    478612    {
    479       long tmp = p - multMod (result[d], q[i], p);
     613      unsigned long tmp = p - multMod (result[d], q[i], p);
    480614      a[d + i] += tmp;
    481       a[d + i] %= p;
    482     }
    483 
    484     while(a[dega] == 0 && dega >= 0)
     615      if (a[d + i] >= p)
     616      {
     617        a[d + i] -= p;
     618      }
     619    }
     620
     621    while(dega >= 0 && a[dega] == 0)
    485622    {
    486623      dega--;
     
    515652    {
    516653      result[i + j] += multMod (a[i], b[j], p);
    517       result[i + j] %= p;
     654      if (result[i + j] >= p)
     655      {
     656        result[i + j] -= p;
     657      }
    518658    }
    519659  }
  • Singular/minpoly.h

    rae1e24 rf613a24  
    11/***********************************************************************************
    2  * Copyright (C) 2011 Sebastian Jambor                                             *
     2 * Author: Sebastian Jambor, 2011                                                  *
     3 * (C) GPL (e-mail from June 6, 2012, 17:00:31 MESZ)                               *
    34 * sebastian@momo.math.rwth-aachen.de                                              *
    45 *                                                                                 *
     
    110111    unsigned long **matrix;
    111112    unsigned *pivots;
     113    unsigned *nonPivots;
    112114    unsigned rows;
    113115
     
    135137    // If no such number exists, return -1.
    136138    int findSmallestNonpivot();
     139
     140    int findLargestNonpivot();
    137141};
    138142
     
    161165unsigned long modularInverse(long long x, long long p);
    162166
    163 void vectorMatrixMult(unsigned long* vec, unsigned long **mat, unsigned long* result, unsigned n, unsigned long p);
     167void vectorMatrixMult(unsigned long* vec, unsigned long **mat, unsigned **nonzeroIndices, unsigned *nonzeroCounts, unsigned long* result, unsigned n, unsigned long p);
    164168
    165169// a is a vector of length at least dega + 1, and q is a vector of length at least degq + 1,
Note: See TracChangeset for help on using the changeset viewer.