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