Changeset 5b2745 in git
- Timestamp:
- May 27, 2011, 6:39:50 PM (12 years ago)
- Branches:
- (u'spielwiese', '91fdef05f09f54b8d58d92a472e9c4a43aa4656f')
- Children:
- 7d1c995f987c51bad98f33e83e328a16ded060ec
- Parents:
- db83bf13b62d944de021f52de5ae04b7ffd0390e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/minpoly.cc
rdb83bf r5b2745 6 6 7 7 #include<cmath> 8 #include<Singular/mod2.h> 8 9 //#include<iomanip> 9 10 … … 12 13 // TODO: avoid code copying, use subclassing instead! 13 14 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 } 15 LinearDependencyMatrix::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 30 LinearDependencyMatrix::~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 42 void LinearDependencyMatrix::resetMatrix () 43 { 44 rows = 0; 45 } 46 47 int 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 56 void 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 85 void 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 93 bool 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 } 112 133 } 113 134 114 135 #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] << " "; 136 std::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] << " "; 131 146 } 132 147 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] << " "; 135 151 } 136 152 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; 139 167 } 140 168 #endif 141 169 142 170 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; 171 NewVectorMatrix::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 186 NewVectorMatrix::~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 197 int 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; 171 204 } 172 205 … … 182 215 //} 183 216 // 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 } 217 void 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 228 void 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 273 void 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]; 207 289 } 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 302 int 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 330 void 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 } 284 346 } 285 347 286 348 #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; 349 void 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; 293 357 } 294 358 #endif 295 359 296 360 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; 361 unsigned 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 465 void rem (unsigned long *a, unsigned long *q, unsigned long p, int °a, 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 487 void quo (unsigned long *a, unsigned long *q, unsigned long p, int °a, 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 529 void 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 545 int 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 588 int 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; 511 619 } 512 620 513 621 514 622 // 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 } 623 long 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 543 655 /* 544 656 int main() { … … 744 856 } 745 857 */ 746
Note: See TracChangeset
for help on using the changeset viewer.