This file is indexed.

/usr/include/linbox/solutions/solve.h is in liblinbox-dev 1.1.6~rc0-4.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* linbox/solutions/solve.h
 *  Evolved from an earlier one by Bradford Hovinen <hovinen@cis.udel.edu>
 *
 * See COPYING for license information.
 */

#ifndef __SOLVE_H
#define __SOLVE_H

#include <vector>
#include <algorithm>

// must fix this list...
#include "linbox/algorithms/wiedemann.h"
#include "linbox/algorithms/rational-solver.h"
#include "linbox/algorithms/diophantine-solver.h"
#include "linbox/blackbox/dense.h"
#include "linbox/matrix/factorized-matrix.h"
#include "linbox/util/debug.h"
#include "linbox/util/error.h"
#include "linbox/vector/vector-domain.h"
#include "linbox/solutions/methods.h"
#include "linbox/algorithms/bbsolve.h"

namespace LinBox 
{

	// for specialization with respect to the DomainCategory
	template< class Vector, class Blackbox, class SolveMethod, class DomainCategory>
	Vector & solve (Vector & 			x,
			const Blackbox &                A,
			const Vector &			b,
			const DomainCategory &        tag,
			const SolveMethod &            M);
	//		SolveStatus * 			s = 0);

	/** \brief Solve Ax = b, for x.
	 *
	 * Vector x such that Ax = b is returned.  
	 In the case of a singular matrix A, if the system is consistent, a random
	 solution is returned by default.  The method parameter may contain
	 an indication that an arbitrary element of the solution space is 
	 acceptable, which can be faster to compute.  
	 If the system is inconsistent the zero vector is returned. 
	 
         \ingroup solutions
        */
	//and the SolveStatus, if non-null, is set to indicate inconsistency.
	template< class Vector, class Blackbox, class SolveMethod>
	Vector & solve (Vector &        		x,
			const Blackbox &                A,
			const Vector &			b,
			const SolveMethod &             M)
	//		SolveStatus * 			s = 0)
	{ 
		return solve(x, A, b, typename FieldTraits<typename Blackbox::Field>::categoryTag(), M);
	}

	// the solve with default method
	template< class Vector, class Blackbox>
	Vector& solve(Vector& x, const Blackbox& A, const Vector& b)
	{ return solve(x, A, b, Method::Hybrid()); }

	// in methods.h FoobarMethod and Method::Foobar are the same class.
	// in methods.h template<BB> bool useBB(const BB& A) is defined.

	// specialize this on blackboxes which have local methods
	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const Method::Hybrid& m)
	{	
		if (useBB(A)) return solve(x, A, b, Method::Blackbox(m)); 
		else return solve(x, A, b, Method::Elimination(m));
	}

	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const Method::Blackbox& m)
	{ 
		// what is chosen here should be best and/or most reliable currently available choice
		// 		integer c; A.field().cardinality(c);
		// 		if (c < 100) return solve(x, A, b, Method::BlockLanczos(m));
		return solve(x, A, b, Method::Wiedemann(m));
	}

	// temporary - fix this
#define inBlasRange(p) true

	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const Method::Elimination& m)
	{ 
		integer c, p;
		A.field().cardinality(c);
		A.field().characteristic(p);
		//if ( p == 0 || (c == p && inBlasRange(p)) )
		return solve(x, A, b, 
			     typename FieldTraits<typename BB::Field>::categoryTag(), 
			     Method::BlasElimination(m)); 
  		//else 
		//	return solve(x, A, b, 
		//			typename FieldTraits<typename BB::Field>::categoryTag(), 
		//			Method::NonBlasElimination(m)); 
	}

	template <class Vector, class Field> 
	Vector& solve(Vector& x, const SparseMatrix<Field>& A, const Vector& b, 
		      const Method::Elimination& m)
	{	
		//             bool consistent = false;
		// sparse elimination based solver can be called here ?
        	// For now we call the dense one
        	
		return solve(x, A, b, 
			     typename FieldTraits<typename SparseMatrix<Field>::Field>::categoryTag(), 
			     Method::BlasElimination(m)); 

		// 		if ( ! consistent ) {  // we will return the zero vector
		// 			typename Field::Element zero; A.field().init(zero, 0);
		// 			for (typename Vector::iterator i = x.begin(); i != x.end(); ++i) *i = zero;
		// 		}
		// 		return x;
	}
	// BlasElimination section ///////////////////

	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const RingCategories::ModularTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		BlasBlackbox<typename BB::Field> B(A); // copy A into a BlasBlackbox
		return solve(x, B, b, tag, m);
	} 

	template <class Vector, class Field> 
	Vector& solve(Vector& x, const BlasBlackbox<Field>& A, const Vector& b, 
		      const RingCategories::ModularTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");

		commentator.start ("Solving linear system (FFLAS LQUP)", "LQUP::left_solve");
		//		bool consistent = false;
		LQUPMatrix<Field> LQUP(A);
		//FactorizedMatrix<Field> LQUP(A);

		LQUP.left_solve(x, b);

		// this should be implemented directly in left_solve 
		//if ( ! consistent ) {  // we will return the zero vector
		//	typename Field::Element zero; A.field().init(zero, 0);
		//	for (typename Vector::iterator i = x.begin(); i != x.end(); ++i) *i = zero;
		//}
		commentator.stop ("done", NULL, "LQUP::left_solve");
		return x;
	} 

	
	/* Integer tag Specialization for Dixon method:
	 * 2 interfaces: 
	 *   - the output is a common denominator and a vector of numerator (no need of rational number)
	 *   - the output is a vector of rational
	 */  


	// error handler for bad use of the integer solver API
	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const RingCategories::IntegerTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		std::cout<<"try to solve system over the integer\n"
			 <<"the API need either \n"
			 <<" - a vector of rational as the solution \n"
			 <<" - or an integer for the common denominator and a vector of integer for the numerators\n\n";
		throw LinboxError("bad use of integer API solver\n");
		
	} 

	// error handler for non defined solver over rational domain
	template <class RatVector, class Vector, class BB, class MethodTraits> 
	Vector& solve(RatVector& x, const BB& A, const Vector& b, 
		      const RingCategories::RationalTag & tag, 
		      const MethodTraits& m)
	{ 
		throw LinboxError("LinBox ERROR: solver not yet defined over rational domain");
	}
	
	// error handler for non defined solver over rational domain
	template <class Vector, class BB, class MethodTraits> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const RingCategories::RationalTag & tag, 
		      const MethodTraits& m)
	{ 
		throw LinboxError("LinBox ERROR: solver not yet defined over rational domain");
	}
	
	
	/*
	 * 1st integer solver API :
	 * solution is a vector of rational numbers
	 * RatVector is assumed to be the type of a vector of rational number
	 */	

	// default API (method is BlasElimination)
	template<class RatVector, class Vector, class BB>	
	RatVector& solve(RatVector& x, const BB &A, const Vector &b){
		return solve(x, A, b, Method::BlasElimination());
	}

	// API with Hybrid method
	template<class RatVector, class Vector, class BB>	
	RatVector& solve(RatVector& x, const BB &A, const Vector &b, const Method::Hybrid &m){
		if (useBB(A)) 
			return solve(x, A, b, Method::Blackbox(m)); 
		else 
			return solve(x, A, b, Method::Elimination(m));
	}

	// API with Blackbox method
	template<class RatVector, class Vector, class BB>	
	RatVector& solve(RatVector& x, const BB &A, const Vector &b, const Method::Blackbox &m){
		return solve(x, A, b, Method::Wiedemann(m));
	}

	// API with Elimination method
	template<class RatVector, class Vector, class BB>	
	RatVector& solve(RatVector& x, const BB &A, const Vector &b, const Method::Elimination &m){
		return solve(x, A, b,  Method::BlasElimination(m));
	}


	// launcher of specialized solver depending on the MethodTrait
	template<class RatVector, class Vector, class BB, class MethodTraits>	
	RatVector& solve(RatVector& x, const BB &A, const Vector &b, const MethodTraits &m){
		return solve(x, A, b, typename FieldTraits<typename BB::Field>::categoryTag(),  m);
	}


	/* Specializations for BlasElimination over the integers
	 */

	// input matrix is generic (copying it into a BlasBlackbox)
	template <class RatVector, class Vector, class BB> 
	RatVector& solve(RatVector& x, const BB& A, const Vector& b, 
			 const RingCategories::IntegerTag & tag, 
			 const Method::BlasElimination& m)
	{ 
		BlasBlackbox<typename BB::Field> B(A); // copy A into a BlasBlackbox
		return solve(x, B, b, tag, m);
	} 
	
	// input matrix is a BlasBlackbox (no copy)
	template <class RatVector, class Vector, class Ring> 
	RatVector& solve(RatVector& x, const BlasBlackbox<Ring>& A, const Vector& b, 
			 const RingCategories::IntegerTag & tag, 
			 const Method::BlasElimination& m)
	{ 
	
		Method::Dixon mDixon(m);
		typename Ring::Element d;
		std::vector< typename Ring::Element> num(A.coldim());
		solve (num, d, A, b, tag, mDixon);
		
		typename RatVector::iterator it_x= x.begin();
		typename std::vector< typename Ring::Element>::const_iterator it_num= num.begin();
		integer n,den;
		A.field().convert(den,d);
		for (; it_x != x.end(); ++it_x, ++it_num){			
			A.field().convert(n, *it_num);
			*it_x = typename RatVector::value_type(n, den);
		}
			
		return x;
	} 

	// input matrix is a DenseMatrix (no copy)
	template <class RatVector, class Vector, class Ring> 
	RatVector& solve(RatVector& x, const DenseMatrix<Ring>& A, const Vector& b, 
			 const RingCategories::IntegerTag & tag, 
			 const Method::BlasElimination& m)
	{ 
		Method::Dixon mDixon(m);
		typename Ring::Element d;
		std::vector< typename Ring::Element> num(A.coldim());
		solve (num, d, A, b, tag, mDixon);
		typename RatVector::iterator it_x= x.begin();
		typename std::vector< typename Ring::Element>::const_iterator it_num= num.begin();
		integer n,den;
		A.field().convert(den,d); 
		for (; it_x != x.end(); ++it_x, ++it_num){			
			A.field().convert(n, *it_num);
			*it_x = typename RatVector::value_type(n, den);
		}
		
		return x;
	} 

	/*
	 * 2nd integer solver API :
	 * solution is a formed by a common denominator and a vector of integer numerator
	 * solution is num/d
	 */
	
	
	// default API (method is BlasElimination)
	template< class Vector, class BB>
	Vector& solve(Vector &x, typename BB::Field::Element &d, const BB &A, const Vector &b){
		return solve(x, d, A, b, typename FieldTraits<typename BB::Field>::categoryTag(),  Method::BlasElimination());
	}
		
	// launcher of specialized solver depending on the MethodTraits
	template< class Vector, class BB, class MethodTraits>
	Vector& solve(Vector &x, typename BB::Field::Element &d, const BB &A, const Vector &b, const MethodTraits &m){
		return solve(x, d, A, b, typename FieldTraits<typename BB::Field>::categoryTag(), m);
	}
	
	/* Specialization for BlasElimination over the integers
	 */
	
	// input matrix is generic (copying it into a BlasBlackbox)
	template <class Vector, class BB> 
	Vector& solve(Vector& x, typename BB::Field::Element &d, const BB& A, const Vector& b, 
		      const RingCategories::IntegerTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		BlasBlackbox<typename BB::Field> B(A); // copy A into a BlasBlackbox
		return solve(x, d, B, b, tag, m);
	} 
	
	// input matrix is a BlasBlackbox (no copy)
	template <class Vector, class Ring> 
	Vector& solve(Vector& x, typename Ring::Element &d, const BlasBlackbox<Ring>& A, const Vector& b, 
		      const RingCategories::IntegerTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		Method::Dixon mDixon(m);
		return solve(x, d, A, b, tag, mDixon);
	} 

	// input matrix is a DenseMatrix (no copy)
	template <class Vector, class Ring> 
	Vector& solve(Vector& x, typename Ring::Element &d, const DenseMatrix<Ring>& A, const Vector& b, 
		      const RingCategories::IntegerTag & tag, 
		      const Method::BlasElimination& m)
	{ 
		Method::Dixon mDixon(m);
		return solve(x, d, A, b, tag, mDixon);
	}



	/** \brief solver specialization with the 2nd API and DixonTraits over integer (no copying)
	 */
	template <class Vector, class Ring> 
	Vector& solve(Vector& x, typename Ring::Element &d, const BlasBlackbox<Ring>& A, const Vector& b, 
		      const RingCategories::IntegerTag tag, Method::Dixon& m)
	{ 
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");

		commentator.start ("Padic Integer Blas-based Solving", "solving");
		
		typedef Modular<double> Field;
		// 0.7213475205 is an upper approximation of 1/(2log(2))
		RandomPrimeIterator genprime( 26-(int)ceil(log((double)A.rowdim())*0.7213475205)); 
		RationalSolver<Ring, Field, RandomPrimeIterator, DixonTraits> rsolve(A.field(), genprime); 			
		SolverReturnStatus status = SS_OK;

		// if singularity unknown and matrix is square, we try nonsingular solver
		switch ( m.singular() ) {
		case Specifier::SINGULARITY_UNKNOWN:
			switch (A.rowdim() == A.coldim() ? 
				status=rsolve.solveNonsingular(x, d, A, b, false ,m.maxTries()) : SS_SINGULAR) {				
			case SS_OK:
				m.singular(Specifier::NONSINGULAR);				
				break;					
			case SS_SINGULAR:
				switch (m.solution()){
				case DixonTraits::DETERMINIST:
					status= rsolve.monolithicSolve(x, d, A, b, false, false, m.maxTries(), 
								       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
					break;					
				case DixonTraits::RANDOM:
					status= rsolve.monolithicSolve(x, d, A, b, false, true, m.maxTries(), 
								       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
					break;					
				case DixonTraits::DIOPHANTINE:
					{ 
						DiophantineSolver<RationalSolver<Ring,Field,RandomPrimeIterator, DixonTraits> > dsolve(rsolve);
						status= dsolve.diophantineSolve(x, d, A, b, m.maxTries(),
										(m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
                                        }
                                        break;					
				default:
					break;
				}			
				break;
			default:
                                break;
			}
			break;
			
		case Specifier::NONSINGULAR:
			rsolve.solveNonsingular(x, d, A, b, false ,m.maxTries());
			break;
			    
		case Specifier::SINGULAR:
			switch (m.solution()){
			case DixonTraits::DETERMINIST:
				status= rsolve.monolithicSolve(x, d, A, b, 
							       false, false, m.maxTries(), 
							       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
				break;
				
			case DixonTraits::RANDOM:
				status= rsolve.monolithicSolve(x, d, A, b, 
							       false, true, m.maxTries(), 
							       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
				break;
				
			case DixonTraits::DIOPHANTINE:
				{
					DiophantineSolver<RationalSolver<Ring,Field,RandomPrimeIterator, DixonTraits> > dsolve(rsolve);
					status= dsolve.diophantineSolve(x, d, A, b, m.maxTries(),
									(m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
                                }
				break;
				
			//default:
			//	break;
			}		
		default:			    
			break;
		}

		commentator.stop("done", NULL, "solving");

		if ( status == SS_INCONSISTENT ) {  
			throw LinboxMathInconsistentSystem("Linear system is inconsistent");
//			typename Ring::Element zero; A.field().init(zero, 0);
// 			for (typename Vector::iterator i = x.begin(); i != x.end(); ++i) *i = zero;
		}
		return x;
	}	

	/** \brief solver specialization with the 2nd API and DixonTraits over integer (no copying)
	 */
	template <class Vector, class Ring> 
	Vector& solve(Vector& x, typename Ring::Element &d, const DenseMatrix<Ring>& A, const Vector& b, 
		      const RingCategories::IntegerTag tag, Method::Dixon& m)
	{  
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");
		
		commentator.start ("Padic Integer Blas-based Solving", "solving");
		
		typedef Modular<double> Field;
		// 0.7213475205 is an upper approximation of 1/(2log(2))
		RandomPrimeIterator genprime( 26-(int)ceil(log((double)A.rowdim())*0.7213475205)); 
		RationalSolver<Ring, Field, RandomPrimeIterator, DixonTraits> rsolve(A.field(), genprime); 			
		SolverReturnStatus status = SS_OK;
		// if singularity unknown and matrix is square, we try nonsingular solver
		switch ( m.singular() ) {
		case Specifier::SINGULARITY_UNKNOWN:
			switch (A.rowdim() == A.coldim() ? 
				status=rsolve.solveNonsingular(x, d, A, b, false ,m.maxTries()) : SS_SINGULAR) {				
			case SS_OK:
				m.singular(Specifier::NONSINGULAR);				
				break;					
			case SS_SINGULAR:
				switch (m.solution()){
				case DixonTraits::DETERMINIST:
					status= rsolve.monolithicSolve(x, d, A, b, false, false, m.maxTries(), 
								       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
					break;					
				case DixonTraits::RANDOM:
					status= rsolve.monolithicSolve(x, d, A, b, false, true, m.maxTries(), 
								       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
					break;					
				case DixonTraits::DIOPHANTINE:
					DiophantineSolver<RationalSolver<Ring,Field,RandomPrimeIterator, DixonTraits> > dsolve(rsolve);
					status= dsolve.diophantineSolve(x, d, A, b, m.maxTries(),
									(m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
					break;					
				//default:
				//	break;
				}			
				break;
			}
			
		case Specifier::NONSINGULAR:
			rsolve.solveNonsingular(x, d, A, b, false ,m.maxTries());
			break;
			    
		case Specifier::SINGULAR:
			switch (m.solution()){
			case DixonTraits::DETERMINIST:
				status= rsolve.monolithicSolve(x, d, A, b, 
							       false, false, m.maxTries(), 
							       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
				break;
				
			case DixonTraits::RANDOM:
				status= rsolve.monolithicSolve(x, d, A, b, 
							       false, true, m.maxTries(), 
							       (m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
				break;
				
			case DixonTraits::DIOPHANTINE:
				DiophantineSolver<RationalSolver<Ring,Field,RandomPrimeIterator, DixonTraits> > dsolve(rsolve);
				status= dsolve.diophantineSolve(x, d, A, b, m.maxTries(),
								(m.certificate()? SL_LASVEGAS: SL_MONTECARLO));
				break;
				
			//default:
			//	break;
			}		
		default:			    
			break;
		}

		commentator.stop("done", NULL, "solving");
		if ( status == SS_INCONSISTENT ) {  
			throw LinboxMathInconsistentSystem("Linear system is inconsistent");
// 			typename Ring::Element zero; A.field().init(zero, 0);
// 			for (typename Vector::iterator i = x.begin(); i != x.end(); ++i) *i = zero;
		}
		return x;	
	}	

	/*
	  struct BlasEliminationCRASpecifier;
	  // Extra case put in (1) for timing comparison or (2) for parallelism or 
	  // (3) as an example of how we might leave an abandoned choice around in a 
	  // callable state for future reference 
	  template <class Vector, class Field> 
	  Vector& solve(Vector& x, const DenseMatrix<Field>& A, const Vector& b, 
	  const RingCategories::IntegerTag & tag, 
	  const BlasEliminationCRASpecifier & m)
	  { // (low priority) J-G puts in code using CRA object CRA and solve(x, A, b, ModularTag, Method::BlasElimination) 
	  typename Field::Element zero; A.field().init(zero, 0);
	  for (typename Vector::iterator i = x.begin(); i != x.end(); ++i) *i = zero;
	  return x;
	  } 
	*/

	// NonBlasElimination section ////////////////

	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const RingCategories::ModularTag & tag, 
		      const Method::NonBlasElimination& m)
	{	DenseMatrix<typename BB::Field> B(A); // copy
		return solve(x, B, b, tag, m);
	}

	// specialization when no need to copy
	template <class Vector, class Field> 
	Vector& solve(Vector& x, const DenseMatrix<Field>& A, const Vector& b, 
		      const RingCategories::ModularTag & tag, 
		      const Method::NonBlasElimination& m)
	{ //Do we have a non blas elimination?  There was not one in the original solve.h (now algorithms/bbsolve.h).
		return x;
	}

	// note: no need for NonBlasElimination when RingCategory is integer

	// Lanczos ////////////////
	// may throw SolverFailed or InconsistentSystem
	
	// 	template <class Vector, class BB> 
	// 	Vector& solve(Vector& x, const BB& A, const Vector& b, 
	// 		      const RingCategories::ModularTag & tag, 
	// 		      const Method::Lanczos& m)
	// 	{
	// 		solve(A, x, b, A.field(), m);
	// 		return x;
	// 	}



	// 	template <class Vector, class BB> 
	// 	Vector& solve(Vector& x, const BB& A, const Vector& b, 
	// 		      const RingCategories::ModularTag & tag, 
	// 		      const Method::BlockLanczos& m)
	// 	{
	//             try { 
	//                 solve(A, x, b, A.field(), m); 
	//             } catch (SolveFailed) {
	//                 typename BB::Field::Element zero; A.field().init(zero, 0);
	//                 for (typename Vector::iterator i = x.begin(); 
	//                      i != x.end(); ++i) 
	//                     *i = zero;
	//             }
	//             return x;
	// 	}

	// Wiedemann section ////////////////

	// may throw SolverFailed or InconsistentSystem
	template <class Vector, class BB> 
	Vector& solve(Vector& x, const BB& A, const Vector& b, 
		      const RingCategories::ModularTag & tag, 
		      const Method::Wiedemann& m)
	{
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");
		
		// adapt to earlier signature of wiedemann solver
		solve(A, x, b, A.field(), m);
		return x;
	}


	/* remark 1.  I used copy constructors when switching method types.
	   But if the method types are (empty) child classes of a common  parent class containing
	   all the information, then casts can be used in place of copies.
	*/ 

} // LinBox



#include "linbox/field/modular.h"
#include "linbox/algorithms/rational-cra.h"
#include "linbox/algorithms/rational-cra-early-multip.h"
#include "linbox/randiter/random-prime.h"
#include "linbox/algorithms/matrix-hom.h"
#include "linbox/vector/vector-traits.h"

namespace LinBox {
   

	template <class Blackbox, class Vector, class MyMethod>
	struct IntegerModularSolve {       
		const Blackbox &A;
		const Vector &B;
		const MyMethod &M;

		IntegerModularSolve(const Blackbox& b, const Vector& v, const MyMethod& n) 
			: A(b), B(v), M(n) {}
        
        
		template<typename Field>
		typename Rebind<Vector, Field>::other& operator()(typename Rebind<Vector, Field>::other& x, const Field& F) const {
			typedef typename Blackbox::template rebind<Field>::other FBlackbox;
			FBlackbox * Ap;
			MatrixHom::map(Ap, A, F);

			typedef typename Rebind<Vector, Field>::other FVector;
			Hom<typename Blackbox::Field, Field> hom(A.field(), F);
			FVector Bp(B.size());
			typename Vector::const_iterator Bit = B.begin();
			typename FVector::iterator      Bpit = Bp.begin();
			for( ; Bit != B.end(); ++Bit, ++Bpit)
				hom.image (*Bpit, *Bit);

			VectorWrapper::ensureDim (x, A.coldim());
			solve( x, *Ap, Bp, M);
			delete Ap;

			return x;
		}            
	};

	// may throw SolverFailed or InconsistentSystem
	template <class Vector, class BB, class MyMethod> 
	Vector& solve(Vector& x, typename BB::Field::Element& d, const BB& A, const Vector& b, 
		      const RingCategories::IntegerTag & tag, 
		      const MyMethod& M)
	{
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");

		commentator.start ("Integer CRA Solve", "Isolve");

		RandomPrimeIterator genprime( 26 -(int)ceil(log((double)A.rowdim())*0.7213475205)); 
		//         RationalRemainder< Modular<double> > rra((double)
		//                                                  ( A.coldim()/2.0*log((double) A.coldim()) ) );
	
		RationalRemainder< EarlyMultipRatCRA< Modular<double> > > rra(3UL);
		IntegerModularSolve<BB,Vector,MyMethod> iteration(A, b, M);

		// use of integer due to non genericity of rra (PG 2005-09-01)
		Integer den;
		std::vector< Integer > num(A.coldim());
		rra(num, den, iteration, genprime);
		//rra(x, d, iteration, genprime);
		
		typename Vector::iterator it_x= x.begin();
		typename std::vector<Integer>::const_iterator it_num= num.begin();
		
		// convert the result
		for (; it_x != x.end(); ++it_x, ++it_num)
			A.field().init(*it_x, *it_num);
		A.field().init(d, den);

		commentator.stop ("done", NULL, "Isolve");
		return x;
	}
	
	template <class RatVector, class Vector, class BB, class MyMethod> 
	RatVector& solve(RatVector& x, const BB& A, const Vector& b, 
			 const RingCategories::IntegerTag & tag, 
			 const MyMethod& M)
	{
		if ((A.coldim() != x.size()) || (A.rowdim() != b.size()))
			throw LinboxError("LinBox ERROR: dimension of data are not compatible in system solving (solving impossible)");

		commentator.start ("Rational CRA Solve", "Rsolve");
		typename BB::Field::Element den;
		std::vector<typename BB::Field::Element > num(A.coldim());
		solve (num, den, A, b, tag, M);
		typename RatVector::iterator it_x= x.begin();
		typename std::vector<typename BB::Field::Element>::const_iterator it_num= num.begin();
		integer n,d;
		A.field().convert(d,den); 
		for (; it_x != x.end(); ++it_x, ++it_num){			
			A.field().convert(n, *it_num);
			*it_x = typename RatVector::value_type(n, d);
		}
		commentator.stop ("done", NULL, "Rsolve");
		return x;
	}
    
} // LinBox




#endif // __SOLVE_H