1 /*
2  * Copyright(C) LinBox
3  *
4  * ========LICENCE========
5  * This file is part of the library LinBox.
6  *
7  * LinBox is free software: you can redistribute it and/or modify
8  * it under the terms of the  GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  * ========LICENCE========
21  *
22  * Written by Clément Pernet
23  */
24 
25 #pragma once
26 
27 #include <linbox/matrix/dense-matrix.h>
28 #include <linbox/matrix/sparse-matrix.h>
29 #include <linbox/solutions/methods.h>
30 namespace LinBox {
31         //
32         // row echelon
33         //
34 
35         /**
36          * \brief rowEchelon specialisation for DenseElimination with DenseMatrix and ModularTag.
37          */
38     template <class Field>
rowEchelon(DenseMatrix<Field> & E,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)39     inline size_t rowEchelon (DenseMatrix<Field>& E, const DenseMatrix<Field>& A,
40                               const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
41     {
42         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()));
43 
44         size_t m = A.rowdim();
45         size_t n = A.coldim();
46         size_t* P = new size_t[m];
47         size_t* Q = new size_t[n];
48         const Field& F = A.field();
49 
50         E = A;
51 
52         size_t R = FFPACK::RowEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
53 
54         FFPACK::getEchelonForm (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, Q,
55                                 E.getPointer(), E.getStride());
56 
57         delete[] P;
58         delete[] Q;
59         return R;
60     }
61 
62 
63         /**
64          * \brief rowEchelon with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
65          */
66     template <class Field>
rowEchelon(DenseMatrix<Field> & E,DenseMatrix<Field> & T,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)67     inline size_t rowEchelon (DenseMatrix<Field>& E, DenseMatrix<Field>& T, const DenseMatrix<Field>& A,
68                               const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
69     {
70         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()) &&
71                      (A.rowdim() == T.rowdim()) && (T.rowdim() == T.coldim()) );
72 
73         size_t m = A.rowdim();
74         size_t n = A.coldim();
75         size_t* P = new size_t[m];
76         size_t* Q = new size_t[n];
77         const Field& F = A.field();
78 
79         E = A;
80 
81         size_t R = FFPACK::RowEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
82 
83         FFPACK::getEchelonTransform (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, P, Q,
84                                      E.getPointer(), E.getStride(), T.getPointer(), T.getStride());
85         FFPACK::getEchelonForm (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, Q,
86                                 E.getPointer(), E.getStride());
87 
88         delete[] P;
89         delete[] Q;
90         return R;
91     }
92 
93         //
94         // row echelonize
95         //
96         /**
97          * \brief rowEchelonize specialisation for DenseElimination with DenseMatrix and ModularTag.
98          */
99     template <class Field>
rowEchelonize(DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)100     inline size_t rowEchelonize (DenseMatrix<Field>& A,
101                                  const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
102     {
103 
104         size_t m = A.rowdim();
105         size_t n = A.coldim();
106         size_t* P = new size_t[m];
107         size_t* Q = new size_t[n];
108         const Field& F = A.field();
109 
110         size_t R = FFPACK::RowEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, false);
111 
112         FFPACK::getEchelonForm (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, Q,
113                                 A.getPointer(), A.getStride());
114 
115         delete[] P;
116         delete[] Q;
117         return R;
118     }
119 
120         /**
121          * \brief rowEchelonize with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
122          */
123     template <class Field>
rowEchelonize(DenseMatrix<Field> & A,DenseMatrix<Field> & T,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)124     inline size_t rowEchelonize (DenseMatrix<Field>& A, DenseMatrix<Field>& T,
125                                  const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
126     {
127         linbox_check((A.rowdim() == T.rowdim()) && (T.rowdim() == T.coldim()));
128 
129         size_t m = A.rowdim();
130         size_t n = A.coldim();
131         size_t* P = new size_t[m];
132         size_t* Q = new size_t[n];
133         const Field& F = A.field();
134 
135         size_t R = FFPACK::RowEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, true);
136 
137         FFPACK::getEchelonTransform (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, P, Q,
138                                      A.getPointer(), A.getStride(), T.getPointer(), T.getStride());
139         FFPACK::getEchelonForm (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, Q, A.getPointer(), A.getStride());
140 
141         delete[] P;
142         delete[] Q;
143         return R;
144     }
145 
146         //
147         // reduced row echelon
148         //
149 
150         /**
151          * \brief reducedRowEchelon specialisation for DenseElimination with DenseMatrix and ModularTag.
152          */
153     template <class Field>
reducedRowEchelon(DenseMatrix<Field> & E,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)154     inline size_t reducedRowEchelon (DenseMatrix<Field>& E, const DenseMatrix<Field>& A,
155                                      const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
156     {
157         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()));
158 
159         size_t m = A.rowdim();
160         size_t n = A.coldim();
161         size_t* P = new size_t[m];
162         size_t* Q = new size_t[n];
163         const Field& F = A.field();
164 
165         E = A;
166 
167         size_t R = FFPACK::ReducedRowEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
168 
169         FFPACK::getReducedEchelonForm (F, FFLAS::FflasUpper, m, n, R, Q, E.getPointer(), E.getStride());
170 
171         delete[] P;
172         delete[] Q;
173         return R;
174     }
175 
176         /**
177          * \brief reducedRowEchelon with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
178          */
179     template <class Field>
reducedRowEchelon(DenseMatrix<Field> & E,DenseMatrix<Field> & T,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)180     inline size_t reducedRowEchelon (DenseMatrix<Field>& E, DenseMatrix<Field>& T, const DenseMatrix<Field>& A,
181                                      const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
182     {
183         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()) &&
184                      (A.rowdim() == T.rowdim()) && (T.rowdim() == T.coldim()) );
185 
186         size_t m = A.rowdim();
187         size_t n = A.coldim();
188         size_t* P = new size_t[m];
189         size_t* Q = new size_t[n];
190         const Field& F = A.field();
191 
192         E = A;
193 
194         size_t R = FFPACK::ReducedRowEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
195 
196         FFPACK::getReducedEchelonTransform (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, P, Q,
197                                             E.getPointer(), E.getStride(), T.getPointer(), T.getStride());
198         FFPACK::getReducedEchelonForm (F, FFLAS::FflasUpper, m, n, R, Q, E.getPointer(), E.getStride());
199 
200         delete[] P;
201         delete[] Q;
202         return R;
203     }
204 
205         //
206         // reduced row echelonize
207         //
208 
209         /**
210          * \brief reducedRowEchelonize specialisation for DenseElimination with DenseMatrix and ModularTag.
211          */
212     template <class Field>
reducedRowEchelonize(DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)213     inline size_t reducedRowEchelonize (DenseMatrix<Field>& A,
214                                         const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
215     {
216         size_t m = A.rowdim();
217         size_t n = A.coldim();
218         size_t* P = new size_t[m];
219         size_t* Q = new size_t[n];
220         const Field& F = A.field();
221 
222         size_t R = FFPACK::ReducedRowEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, false);
223 
224         FFPACK::getReducedEchelonForm (F, FFLAS::FflasUpper, m, n, R, Q,
225                                        A.getPointer(), A.getStride());
226 
227         delete[] P;
228         delete[] Q;
229         return R;
230     }
231 
232         /**
233          * \brief reducedRowEchelonize with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
234          */
235     template <class Field>
reducedRowEchelonize(DenseMatrix<Field> & A,DenseMatrix<Field> & T,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)236     inline size_t reducedRowEchelonize (DenseMatrix<Field>& A, DenseMatrix<Field>& T,
237                                         const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
238     {
239         linbox_check((A.rowdim() == T.rowdim()) && (T.rowdim() == T.coldim()));
240 
241         size_t m = A.rowdim();
242         size_t n = A.coldim();
243         size_t* P = new size_t[m];
244         size_t* Q = new size_t[n];
245         const Field& F = A.field();
246 
247         size_t R = FFPACK::ReducedRowEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, true);
248 
249         FFPACK::getReducedEchelonTransform (F, FFLAS::FflasUpper, FFLAS::FflasUnit, m, n, R, P, Q,
250                                             A.getPointer(), A.getStride(), T.getPointer(), T.getStride());
251         FFPACK::getReducedEchelonForm (F, FFLAS::FflasUpper, m, n, R, Q, A.getPointer(), A.getStride());
252 
253         delete[] P;
254         delete[] Q;
255         return R;
256     }
257 
258         //
259         // column echelon
260         //
261 
262         /**
263          * \brief colEchelon specialisation for DenseElimination with DenseMatrix and ModularTag.
264          */
265     template <class Field>
colEchelon(DenseMatrix<Field> & E,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)266     inline size_t colEchelon (DenseMatrix<Field>& E, const DenseMatrix<Field>& A,
267                               const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
268     {
269         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()));
270 
271         size_t m = A.rowdim();
272         size_t n = A.coldim();
273         size_t* P = new size_t[n];
274         size_t* Q = new size_t[m];
275         const Field& F = A.field();
276 
277         E = A;
278 
279         size_t R = FFPACK::ColumnEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
280 
281         FFPACK::getEchelonForm (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, Q,
282                                 E.getPointer(), E.getStride());
283 
284         delete[] P;
285         delete[] Q;
286         return R;
287     }
288 
289 
290         /**
291          * \brief colEchelon with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
292          */
293     template <class Field>
colEchelon(DenseMatrix<Field> & E,DenseMatrix<Field> & T,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)294     inline size_t colEchelon (DenseMatrix<Field>& E, DenseMatrix<Field>& T, const DenseMatrix<Field>& A,
295                               const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
296     {
297         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()) &&
298                      (A.coldim() == T.rowdim()) && (T.rowdim() == T.coldim()) );
299 
300         size_t m = A.rowdim();
301         size_t n = A.coldim();
302         size_t* P = new size_t[n];
303         size_t* Q = new size_t[m];
304         const Field& F = A.field();
305 
306         E = A;
307 
308         size_t R = FFPACK::ColumnEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
309 
310         FFPACK::getEchelonTransform (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, P, Q,
311                                      E.getPointer(), E.getStride(), T.getPointer(), T.getStride());
312         FFPACK::getEchelonForm (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, Q,
313                                 E.getPointer(), E.getStride());
314 
315         delete[] P;
316         delete[] Q;
317         return R;
318     }
319 
320         //
321         // col echelonize
322         //
323         /**
324          * \brief colEchelonize specialisation for DenseElimination with DenseMatrix and ModularTag.
325          */
326     template <class Field>
colEchelonize(DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)327     inline size_t colEchelonize (DenseMatrix<Field>& A,
328                                  const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
329     {
330 
331         size_t m = A.rowdim();
332         size_t n = A.coldim();
333         size_t* P = new size_t[n];
334         size_t* Q = new size_t[m];
335         const Field& F = A.field();
336 
337         size_t R = FFPACK::ColumnEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, false);
338 
339         FFPACK::getEchelonForm (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, Q,
340                                 A.getPointer(), A.getStride());
341 
342         delete[] P;
343         delete[] Q;
344         return R;
345     }
346 
347         /**
348          * \brief colEchelonize with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
349          */
350     template <class Field>
colEchelonize(DenseMatrix<Field> & A,DenseMatrix<Field> & T,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)351     inline size_t colEchelonize (DenseMatrix<Field>& A, DenseMatrix<Field>& T,
352                                  const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
353     {
354         linbox_check((A.coldim() == T.rowdim()) && (T.rowdim() == T.coldim()));
355 
356         size_t m = A.rowdim();
357         size_t n = A.coldim();
358         size_t* P = new size_t[n];
359         size_t* Q = new size_t[m];
360         const Field& F = A.field();
361 
362         size_t R = FFPACK::ColumnEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, true);
363 
364         FFPACK::getEchelonTransform (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, P, Q,
365                                      A.getPointer(), A.getStride(), T.getPointer(), T.getStride());
366         FFPACK::getEchelonForm (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, Q, A.getPointer(), A.getStride());
367 
368         delete[] P;
369         delete[] Q;
370         return R;
371     }
372 
373         //
374         // reduced col echelon
375         //
376 
377         /**
378          * \brief reducedColEchelon specialisation for DenseElimination with DenseMatrix and ModularTag.
379          */
380     template <class Field>
reducedColEchelon(DenseMatrix<Field> & E,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)381     inline size_t reducedColEchelon (DenseMatrix<Field>& E, const DenseMatrix<Field>& A,
382                                      const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
383     {
384         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()));
385 
386         size_t m = A.rowdim();
387         size_t n = A.coldim();
388         size_t* P = new size_t[n];
389         size_t* Q = new size_t[m];
390         const Field& F = A.field();
391 
392         E = A;
393 
394         size_t R = FFPACK::ReducedColumnEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
395 
396         FFPACK::getReducedEchelonForm (F, FFLAS::FflasLower, m, n, R, Q, E.getPointer(), E.getStride());
397 
398         delete[] P;
399         delete[] Q;
400         return R;
401     }
402 
403         /**
404          * \brief reducedColEchelon with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
405          */
406     template <class Field>
reducedColEchelon(DenseMatrix<Field> & E,DenseMatrix<Field> & T,const DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)407     inline size_t reducedColEchelon (DenseMatrix<Field>& E, DenseMatrix<Field>& T, const DenseMatrix<Field>& A,
408                                      const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
409     {
410         linbox_check((A.coldim() == E.coldim()) && (A.rowdim() == E.rowdim()) &&
411                      (A.coldim() == T.rowdim()) && (T.rowdim() == T.coldim()) );
412 
413         size_t m = A.rowdim();
414         size_t n = A.coldim();
415         size_t* P = new size_t[n];
416         size_t* Q = new size_t[m];
417         const Field& F = A.field();
418 
419         E = A;
420 
421         size_t R = FFPACK::ReducedColumnEchelonForm (F, m, n, E.getPointer(), E.getStride(), P, Q, false);
422 
423         FFPACK::getReducedEchelonTransform (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, P, Q,
424                                             E.getPointer(), E.getStride(), T.getPointer(), T.getStride());
425         FFPACK::getReducedEchelonForm (F, FFLAS::FflasLower, m, n, R, Q, E.getPointer(), E.getStride());
426 
427         delete[] P;
428         delete[] Q;
429         return R;
430     }
431 
432         //
433         // reduced col echelonize
434         //
435 
436         /**
437          * \brief reducedColEchelonize specialisation for DenseElimination with DenseMatrix and ModularTag.
438          */
439     template <class Field>
reducedColEchelonize(DenseMatrix<Field> & A,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)440     inline size_t reducedColEchelonize (DenseMatrix<Field>& A,
441                                         const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
442     {
443         size_t m = A.rowdim();
444         size_t n = A.coldim();
445         size_t* P = new size_t[n];
446         size_t* Q = new size_t[m];
447         const Field& F = A.field();
448 
449         size_t R = FFPACK::ReducedColumnEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, false);
450 
451         FFPACK::getReducedEchelonForm (F, FFLAS::FflasLower, m, n, R, Q,
452                                        A.getPointer(), A.getStride());
453 
454         delete[] P;
455         delete[] Q;
456         return R;
457     }
458 
459         /**
460          * \brief reducedColEchelonize with transformation specialisation for DenseElimination with DenseMatrix and ModularTag.
461          */
462     template <class Field>
reducedColEchelonize(DenseMatrix<Field> & A,DenseMatrix<Field> & T,const RingCategories::ModularTag & tag,const Method::DenseElimination & M)463     inline size_t reducedColEchelonize (DenseMatrix<Field>& A, DenseMatrix<Field>& T,
464                                         const RingCategories::ModularTag& tag, const Method::DenseElimination& M)
465     {
466         linbox_check((A.coldim() == T.rowdim()) && (T.rowdim() == T.coldim()));
467 
468         size_t m = A.rowdim();
469         size_t n = A.coldim();
470         size_t* P = new size_t[n];
471         size_t* Q = new size_t[m];
472         const Field& F = A.field();
473 
474         size_t R = FFPACK::ReducedColumnEchelonForm (F, m, n, A.getPointer(), A.getStride(), P, Q, true);
475 
476         FFPACK::getReducedEchelonTransform (F, FFLAS::FflasLower, FFLAS::FflasUnit, m, n, R, P, Q,
477                                             A.getPointer(), A.getStride(), T.getPointer(), T.getStride());
478         FFPACK::getReducedEchelonForm (F, FFLAS::FflasLower, m, n, R, Q, A.getPointer(), A.getStride());
479 
480         delete[] P;
481         delete[] Q;
482         return R;
483     }
484 }
485 /* -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
486 // vim:sts=4:sw=4:ts=4:et:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
487 
488