1 // -*- C++ -*- 2 //============================================================================================== 3 // 4 // This file is part of LiDIA --- a library for computational number theory 5 // 6 // Copyright (c) 1994--2001 the LiDIA Group. All rights reserved. 7 // 8 // See http://www.informatik.tu-darmstadt.de/TI/LiDIA/ 9 // 10 //---------------------------------------------------------------------------------------------- 11 // 12 // $Id$ 13 // 14 // Author : 15 // Changes : See CVS log 16 // 17 //============================================================================================== 18 19 20 #ifndef LIDIA_LANCZOS_H_GUARD_ 21 #define LIDIA_LANCZOS_H_GUARD_ 22 23 #ifndef LIDIA_LIDIA_H_GUARD_ 24 # include "LiDIA/LiDIA.h" 25 #endif 26 27 #include <memory> 28 #include <vector> 29 #include <cstring> // declares memcpy() 30 31 #ifdef DEBUG 32 #include <cassert> 33 #endif 34 35 36 #ifdef LIDIA_NAMESPACE 37 namespace LiDIA { 38 # define IN_NAMESPACE_LIDIA 39 #endif 40 41 42 43 // 44 // globale lanczos definitions 45 // 46 47 #define WordSize BITS_PER_LONG 48 void bin_out(const unsigned long); 49 50 // 51 // Bitmask for operations 52 // 53 #define One_mask (~(0UL)) 54 #define Bit_mask(k) (1UL<<(WordSize-1-(k))) 55 56 class index_list 57 { 58 public: 59 typedef size_t size_type; 60 typedef long value_type; 61 62 private: 63 size_type length; 64 value_type *list; 65 66 public: index_list(const size_type number)67 index_list(const size_type number) 68 { 69 if (number == 0) 70 lidia_error_handler("lanczos","index_list(size_t)::length " 71 "is non-positive"); 72 length = number; 73 list = new value_type [number]; 74 memset(list, 0, length * sizeof(value_type)); 75 } 76 ~index_list()77 ~index_list() 78 { 79 delete[] list; 80 } 81 get(const size_type pos)82 value_type get(const size_type pos) const 83 { 84 if (pos >= length) 85 lidia_error_handler("index_list","pos >= length"); 86 return list[pos]; 87 } 88 put(const size_type pos,const value_type value)89 void put(const size_type pos, const value_type value) 90 { 91 if (pos >= length) 92 lidia_error_handler("index_list","pos >= length"); 93 list[pos] = value; 94 } 95 number()96 size_type number() const 97 { 98 return length; 99 } 100 print()101 void print() const 102 { 103 printf("\nIndex_List:\t"); 104 for (size_type i = 0; i < length; i++) 105 printf(" [%ld] %ld\n", i, list[i]); 106 } 107 clear()108 void clear() 109 { 110 memset(list, 0, length * sizeof(value_type)); 111 } 112 }; 113 114 115 116 //************************************************************************ 117 // 118 // Class Lanczos_Sparse_Vector 119 // helping class for a sparse matrix 120 // 121 //************************************************************************ 122 123 class lanczos_sparse_vector 124 { 125 friend class lanczos_sparse_matrix; 126 127 public: 128 typedef size_t size_type; 129 typedef unsigned long value_type; 130 131 private: 132 size_type length; 133 size_type number_of_entries; // number of non zero entries 134 value_type *entries; // array of entries 135 136 public: 137 lanczos_sparse_vector(); 138 lanczos_sparse_vector(const size_type len, 139 const size_type number); 140 lanczos_sparse_vector(const lanczos_sparse_vector & vector); 141 142 ~lanczos_sparse_vector(); 143 144 const lanczos_sparse_vector &operator = (const lanczos_sparse_vector&v) 145 { 146 if (&v != this) 147 { 148 delete[] entries; 149 150 length = v.length; 151 number_of_entries = v.number_of_entries; 152 entries = new value_type [number_of_entries]; 153 154 memcpy(entries, v.entries, number_of_entries*sizeof(value_type)); 155 } 156 return *this; 157 } 158 get_entries()159 value_type *get_entries() const 160 { 161 return entries; 162 } 163 set_entries(value_type * values,const size_type number,const size_type len)164 void set_entries(value_type *values, const size_type number, 165 const size_type len) 166 { 167 if( entries != values ) { 168 delete[] entries; 169 entries = values; 170 number_of_entries = number; 171 length = len; 172 } 173 } 174 get_length()175 size_type get_length() const 176 { 177 return length; 178 } 179 get_number_of_entries()180 size_type get_number_of_entries() const 181 { 182 return number_of_entries; 183 } 184 put_number_of_entries(const size_type number)185 void put_number_of_entries(const size_type number) 186 { 187 number_of_entries = number; 188 } 189 get_entry(const size_type i)190 value_type get_entry(const size_type i) const 191 { 192 if(i >= number_of_entries) 193 lidia_error_handler("lanczos_sparse_vector", "out of range"); 194 return entries[i]; 195 } 196 put_entry(const size_type i,const value_type value)197 void put_entry(const size_type i, const value_type value) 198 { 199 if(i >= number_of_entries || value > length) 200 lidia_error_handler("lanczos_sparse_vector", "out of range"); 201 entries[i] = value; 202 } 203 clear()204 void clear() 205 { 206 memset(entries, 0, number_of_entries * sizeof(value_type)); 207 } 208 209 void print() const; 210 lanczos_sparse_vector &fill_random (long part, int ratio); 211 }; 212 213 214 215 //*********************************************************************** 216 // 217 // small dense matrix over GF(2) (Wordsize x Wordsize) 218 // 219 //*********************************************************************** 220 221 class lanczos_small_matrix 222 { 223 public: 224 typedef size_t size_type; 225 typedef unsigned long value_type; 226 227 private: 228 value_type rows[WordSize]; 229 // matrix is wordsize x wordsize over GF(2) 230 // ulongs are rows 231 232 public: lanczos_small_matrix()233 lanczos_small_matrix() {memset(rows,0,sizeof(rows));}; ~lanczos_small_matrix()234 ~lanczos_small_matrix() {}; 235 236 const lanczos_small_matrix& operator= (const lanczos_small_matrix& matrix) 237 { 238 memcpy(rows, matrix.rows, WordSize * sizeof(value_type)); 239 } 240 put_row(const size_type pos,const value_type row)241 void put_row(const size_type pos, const value_type row) 242 { 243 if (pos >= WordSize) 244 lidia_error_handler("lanczos_small_matrix","put_row::index out" 245 " of range"); 246 rows[pos] = row; 247 } 248 get_row(const size_type pos)249 value_type get_row(const size_type pos) const 250 { 251 if (pos >= WordSize) 252 lidia_error_handler("lanczos_small_matrix","get_row::index out" 253 " of range"); 254 return rows[pos]; 255 } 256 clear()257 void clear() 258 { 259 memset(rows, 0, WordSize * sizeof(value_type)); 260 } 261 lanczos_small_matrix *mult_right(const lanczos_small_matrix& m) const; 262 lanczos_small_matrix *mult_right_transpose(const lanczos_small_matrix& m) const; 263 264 void mult_right_to(const lanczos_small_matrix& m, 265 lanczos_small_matrix& result) const; 266 void mult_right_transpose_to(const lanczos_small_matrix& m, 267 lanczos_small_matrix& result) const; 268 is_zero()269 bool is_zero() const 270 { 271 for (size_type i = 0; i < WordSize; i++) 272 if (rows[i] != 0) 273 return false; 274 return true; 275 } 276 eliminate(const value_type entry)277 void eliminate (const value_type entry) 278 { 279 for (size_type i = 0; i < WordSize; i++) 280 put_row(i, get_row(i) & entry); 281 } 282 add(const lanczos_small_matrix & matrix)283 void add(const lanczos_small_matrix& matrix) 284 { 285 for (size_type i = 0; i < WordSize; i++) 286 put_row(i, matrix.get_row(i) ^ get_row(i)); 287 } 288 289 void print() const; 290 }; 291 292 293 294 //************************************************************************ 295 // 296 // vector block over GF(2) 297 // 298 //************************************************************************ 299 300 class lanczos_vector_block 301 { 302 public: 303 typedef size_t size_type; 304 typedef unsigned long value_type; 305 306 typedef std::vector< std::vector< size_type> > result_vector_type; 307 308 private: 309 size_type length; 310 value_type *rows; 311 312 public: 313 lanczos_vector_block(const size_type len)314 lanczos_vector_block(const size_type len) 315 { 316 if (len == 0) 317 lidia_error_handler("lanczos_vector_block","ct::length is zero"); 318 rows = new value_type [len]; 319 length = len; 320 memset(rows, 0, length * sizeof(value_type)); 321 } 322 lanczos_vector_block(const lanczos_vector_block & v)323 lanczos_vector_block(const lanczos_vector_block &v) 324 { 325 length = v.get_length(); 326 rows = new value_type [length]; 327 memcpy(rows, v.rows, length * sizeof(value_type)); 328 } 329 ~lanczos_vector_block()330 ~lanczos_vector_block() 331 { 332 delete[] rows; 333 } 334 get_length()335 size_type get_length() const 336 { 337 return length; 338 } 339 put_row(const size_type pos,const value_type row)340 void put_row(const size_type pos, const value_type row) 341 { 342 if(pos >= length) 343 lidia_error_handler("lanczos_vector_block", "put_row::out of" 344 " range"); 345 rows[pos] = row; 346 } 347 get_row(const size_type pos)348 value_type get_row(const size_type pos) const 349 { 350 if(pos >= length) 351 lidia_error_handler("lanczos_vector_block", "get_row::out of" 352 " range"); 353 return rows[pos]; 354 } 355 clear()356 void clear() 357 { 358 memset(rows, 0, length * sizeof(value_type)); 359 } 360 is_zero()361 bool is_zero() const 362 { 363 for (size_type i = 0; i < length; i++) 364 if (rows[i] != 0) 365 return false; 366 return true; 367 } 368 369 void print() const; 370 371 void read(result_vector_type const& res); 372 result_vector_type result() const; 373 lanczos_small_matrix *mult(const lanczos_vector_block& v) const; 374 lanczos_vector_block *mult_small (const lanczos_small_matrix& m) const; 375 void mult_to(const lanczos_vector_block& v, 376 lanczos_small_matrix& result) const; 377 void mult_small_to (const lanczos_small_matrix& m, 378 lanczos_vector_block& result) const; 379 add(const lanczos_vector_block & vector)380 void add (const lanczos_vector_block& vector) 381 { 382 for (size_type i = 0; i < length; i++) 383 bitwise_xor(i, vector.get_row(i)); 384 } 385 bitwise_xor(const size_type row,const value_type value)386 void bitwise_xor (const size_type row, const value_type value) 387 { 388 if(row >= length) 389 lidia_error_handler("lanczos_vector_block", "bitwise_xor::out of" 390 " range"); 391 rows[row] ^= value; 392 } 393 bitwise_and(const size_type row,const value_type value)394 void bitwise_and (const size_type row, const value_type value) 395 { 396 if(row >= length) 397 lidia_error_handler("lanczos_vector_block", "bitwise_and::out of" 398 " range"); 399 rows[row] &= value; 400 } 401 bitwise_or(const size_type row,const value_type value)402 void bitwise_or (const size_type row, const value_type value) 403 { 404 if(row >= length) 405 lidia_error_handler("lanczos_vector_block", "bitwise_or::out of" 406 " range"); 407 rows[row] |= value; 408 } 409 eliminate(const value_type entry)410 void eliminate(const value_type entry) 411 { 412 for (size_type i = 0; i < length; i++) 413 bitwise_and(i, entry); 414 } 415 }; 416 417 418 419 //************************************************************************ 420 // 421 // big sparse matrix over GF(2) for lanczos 422 // 423 //************************************************************************ 424 425 class lanczos_sparse_matrix 426 { 427 friend struct preprocess; 428 429 public: 430 typedef size_t size_type; 431 typedef lanczos_sparse_vector::value_type value_type; 432 433 private: 434 size_type columns; // number of columns 435 size_type rows; // number of rows 436 lanczos_sparse_vector *entries; // Array of sparse_vectors 437 index_list *row_weight; 438 439 public: 440 lanczos_sparse_matrix(const size_type row, const size_type col); 441 lanczos_sparse_matrix(const char *filename); 442 ~lanczos_sparse_matrix(); 443 444 number_of_columns()445 size_type number_of_columns() const 446 { 447 return columns; 448 } 449 number_of_rows()450 size_type number_of_rows() const 451 { 452 return rows; 453 } 454 put_columns(const size_type col)455 void put_columns(const size_type col) 456 { 457 columns = col; 458 } 459 put_vector(const size_type pos,const lanczos_sparse_vector & v)460 void put_vector(const size_type pos, const lanczos_sparse_vector &v) 461 { // check apa, columns or rows?? 462 entries[pos] = v; 463 } 464 get_vector(const size_type pos)465 lanczos_sparse_vector& get_vector(const size_type pos) 466 { 467 return entries[pos]; 468 } 469 get_vector(const size_type pos)470 const lanczos_sparse_vector& get_vector(const size_type pos) const 471 { 472 return entries[pos]; 473 } 474 475 void delete_vector(const size_type pos); 476 lanczos_vector_block *mult_vectorblock(const lanczos_vector_block& vector_block) const; 477 void mult_vectorblock_to(const lanczos_vector_block& vector_block, 478 lanczos_vector_block& result) const; 479 void print() const; 480 void write(const char *filename) const; 481 void fill_random(const size_type number, const long part, const int ratio); 482 long calculate_weight() const; 483 void delete_rows(const index_list& row_list); 484 }; 485 486 487 488 //*************************************************************************** 489 // 490 // class lanczos 491 // 492 //*************************************************************************** 493 494 class lanczos 495 { 496 public: 497 typedef size_t size_type; 498 typedef unsigned long value_type; 499 500 private: 501 const lanczos_sparse_matrix& A; 502 // vektors 503 lanczos_vector_block *V_next; 504 lanczos_vector_block *V; 505 lanczos_vector_block *V_prev; 506 lanczos_vector_block *V_pprev; 507 lanczos_vector_block *X; 508 509 lanczos_vector_block *dummy1_vec; 510 lanczos_vector_block *dummy2_vec; 511 512 size_type result_rank; // rank of the resultvector 513 514 515 size_type M, N; //rows and columns 516 517 size_type compute_tau2(const lanczos_small_matrix& mt, 518 value_type& S_entry, 519 lanczos_small_matrix& mw_inv) const; 520 521 void compute_result(); 522 void post_process(); 523 void compute_D(lanczos_small_matrix& VAAV, 524 const lanczos_small_matrix& VAV, 525 const lanczos_small_matrix& W_inv, 526 const value_type S, 527 lanczos_small_matrix& eta, 528 lanczos_small_matrix& result) const; 529 530 void compute_E(const lanczos_small_matrix& VAV, 531 const lanczos_small_matrix& W_inv_prev, 532 const value_type S, 533 lanczos_small_matrix& result) const; 534 535 void compute_F(const lanczos_small_matrix& VAV_prev, 536 const lanczos_small_matrix& eta_prev, 537 const lanczos_small_matrix& W_inv_prev, 538 const lanczos_small_matrix& W_inv_pprev, 539 const value_type S, 540 lanczos_small_matrix& result) const; 541 542 public: 543 explicit lanczos (const lanczos_sparse_matrix& matrix); 544 ~lanczos (); 545 void solve (); get_result_rank()546 size_type get_result_rank() const 547 { 548 return result_rank; 549 } 550 get_result()551 const lanczos_vector_block& get_result() const 552 { 553 return *X; 554 } 555 556 //G.A. - removed 'const' keyword get_result()557 lanczos_vector_block& get_result() 558 { 559 return *X; 560 } 561 }; 562 563 564 565 struct preprocess { 566 typedef lanczos_sparse_matrix::size_type size_type; 567 std::auto_ptr<index_list> 568 process(lanczos_sparse_matrix& matrix) const; 569 }; 570 571 572 573 struct postprocess { 574 typedef lanczos_vector_block::size_type size_type; 575 std::auto_ptr<lanczos_vector_block> 576 process(const lanczos_vector_block& vector, 577 const index_list& list) const; 578 }; 579 580 581 582 #ifdef LIDIA_NAMESPACE 583 } // end of namespace LiDIA 584 # undef IN_NAMESPACE_LIDIA 585 #endif 586 587 588 589 #endif // LIDIA_LANCZOS_H_GUARD_ 590