Macaulay2 Engine
Loading...
Searching...
No Matches
mat-elem-ops.hpp
Go to the documentation of this file.
1// Copyright 2013 Michael E. Stillman
2
3#ifndef _mat_elementary_ops_hpp_
4#define _mat_elementary_ops_hpp_
5
37
38#include <memory>
39
40template <typename MT>
42template <typename RT>
43class DMat;
44template <typename RT>
45class SMat;
46
47template <typename RT>
49{
50 public:
51 typedef DMat<RT> Mat;
52 typedef typename Mat::ElementType ElementType;
53 typedef typename RT::Element Element;
54
55 // remove
56 // private:
57 // template <typename It1, typename It2, typename It3>
58 // static void copy_from_iter(const RT& R, It1 loc1, It2 end1, It3 loc2)
59 // {
60 // for (; loc1 != end1; ++loc1, ++loc2) R.set(*loc1, *loc2);
61 // }
62
63 public:
64 static size_t lead_row(const Mat& mat, size_t col)
65 /* returns the largest index row which has a non-zero value in column 'col'.
66 returns -1 if the column has no non-zero entries */
67 {
68 size_t row = mat.numRows();
69 while (row != 0)
70 {
71 --row;
72 if (!mat.ring().is_zero(mat.entry(row, col))) return row;
73 }
74 return static_cast<size_t>(-1);
75 }
76
77 static size_t lead_row(const Mat& mat, size_t col, ElementType& result)
78 /* returns the largest index row which has a non-zero value in column 'col'.
79 Also sets result to be the entry at this index.
80 returns -1 if the column is 0, or if col is out of range
81 No error is flagged. */
82 {
83 size_t row = mat.numRows();
84 while (row != 0)
85 {
86 --row;
87 if (!mat.ring().is_zero(mat.entry(row, col)))
88 {
89 mat.ring().set(result, mat.entry(row, col));
90 return row;
91 }
92 }
93 return static_cast<size_t>(-1);
94 }
95
97 // Row and column operations //
99 // The following routines return false if one of the row or columns given
100 // is out of range.
101
102 static void interchange_rows(Mat& mat, size_t i, size_t j)
103 /* swap rows: row(i) <--> row(j) */
104 {
105 assert(i < mat.numRows());
106 assert(j < mat.numRows());
107 if (i == j) return;
108
109 for (size_t c = 0; c < mat.numColumns(); ++c)
110 mat.ring().swap(mat.entry(i,c), mat.entry(j,c));
111 }
112
113 static void interchange_columns(Mat& mat, size_t i, size_t j)
114 /* swap columns: column(i) <--> column(j) */
115 {
116 assert(i < mat.numColumns());
117 assert(j < mat.numColumns());
118 if (i == j) return;
119
120 for (size_t r = 0; r < mat.numRows(); ++r)
121 mat.ring().swap(mat.entry(r,i), mat.entry(r,j));
122 }
123
124 static void scale_row(Mat& mat, size_t i, const ElementType& a)
125 /* row(i) <- a * row(i) */
126 {
127 assert(i < mat.numRows());
128
129 for (size_t c = 0; c < mat.numColumns(); ++c)
130 mat.ring().mult(mat.entry(i,c), a, mat.entry(i,c));
131 }
132
133 static void scale_column(Mat& mat, size_t i, const ElementType& a)
134 /* column(i) <- a * column(i) */
135 {
136 assert(i < mat.numColumns());
137
138 for (size_t r = 0; r < mat.numRows(); ++r)
139 mat.ring().mult(mat.entry(r,i), a, mat.entry(r,i));
140 }
141
142 static void divide_row(Mat& mat, size_t i, const ElementType& a)
143 /* row(i) <- row(i) / a */
144 {
145 assert(i < mat.numRows());
146
147 for (size_t c = 0; c < mat.numColumns(); ++c)
148 mat.ring().divide(mat.entry(i,c), mat.entry(i,c), a);
149 }
150
151 static void divide_column(Mat& mat, size_t i, const ElementType& a)
152 /* column(i) <- column(i) / a */
153 {
154 assert(i < mat.numColumns());
155
156 for (size_t r = 0; r < mat.numRows(); ++r)
157 mat.ring().divide(mat.entry(r,i), mat.entry(r,i), a);
158 }
159
160 static void row_op(Mat& mat, size_t i, const ElementType& a, size_t j)
161 /* row(i) <- row(i) + a * row(j) */
162 {
163 assert(i < mat.numRows());
164 assert(j < mat.numRows());
165 assert(i != j);
166
167 Element f(mat.ring());
168 mat.ring().set_zero(f);
169
170 for (size_t c = 0; c < mat.numColumns(); ++c)
171 {
172 mat.ring().mult(f, a, mat.entry(j,c));
173 mat.ring().add(mat.entry(i,c), f, mat.entry(i,c));
174 }
175 }
176
177 static void column_op(Mat& mat, size_t i, const ElementType& a, size_t j)
178 /* column(i) <- column(i) + a * column(j) */
179 {
180 assert(i < mat.numColumns());
181 assert(j < mat.numColumns());
182 assert(i != j);
183
184 Element f(mat.ring());
185 mat.ring().set_zero(f);
186
187 for (size_t r = 0; r < mat.numRows(); ++r)
188 {
189 mat.ring().mult(f, a, mat.entry(r,j));
190 mat.ring().add(mat.entry(r,i), f, mat.entry(r,i));
191 }
192 }
193
194 public:
195 static void row2by2(Mat& mat,
196 size_t r1,
197 size_t r2,
198 const ElementType& a1,
199 const ElementType& a2,
200 const ElementType& b1,
201 const ElementType& b2)
202 /* row(r1) <- a1 * row(r1) + a2 * row(r2),
203 row(r2) <- b1 * row(r1) + b2 * row(r2)
204 */
205 {
206 assert(r1 < mat.numRows());
207 assert(r2 < mat.numRows());
208 assert(r1 != r2);
209
210 const RT& ring { mat.ring() };
211 Element f1(ring), f2(ring), g1(ring), g2(ring);
212 ring.set_zero(f1);
213 ring.set_zero(f2);
214 ring.set_zero(g1);
215 ring.set_zero(g2);
216
217 for (size_t c = 0; c < mat.numColumns(); ++c)
218 {
219 ring.mult(f1, a1, mat.entry(r1,c));
220 ring.mult(f2, a2, mat.entry(r2,c));
221 ring.add(f1, f1, f2);
222
223 ring.mult(g1, b1, mat.entry(r1,c));
224 ring.mult(g2, b2, mat.entry(r2,c));
225 ring.add(g1, g1, g2);
226
227 ring.set(mat.entry(r1,c), f1);
228 ring.set(mat.entry(r2,c), g1);
229 }
230 }
231
232 static void column2by2(Mat& mat,
233 size_t c1,
234 size_t c2,
235 const ElementType& a1,
236 const ElementType& a2,
237 const ElementType& b1,
238 const ElementType& b2)
239 /* column(c1) <- a1 * column(c1) + a2 * column(c2),
240 column(c2) <- b1 * column(c1) + b2 * column(c2)
241 */
242 {
243 assert(c1 < mat.numColumns());
244 assert(c2 < mat.numColumns());
245 assert(c1 != c2);
246
247 const RT& ring { mat.ring() };
248 Element f1(ring), f2(ring), g1(ring), g2(ring);
249 ring.set_zero(f1);
250 ring.set_zero(f2);
251 ring.set_zero(g1);
252 ring.set_zero(g2);
253
254 for (size_t r = 0; r < mat.numRows(); ++r)
255 {
256 ring.mult(f1, a1, mat.entry(r, c1));
257 ring.mult(f2, a2, mat.entry(r, c2));
258 ring.add(f1, f1, f2);
259
260 ring.mult(g1, b1, mat.entry(r, c1));
261 ring.mult(g2, b2, mat.entry(r, c2));
262 ring.add(g1, g1, g2);
263
264 ring.set(mat.entry(r, c1), f1);
265 ring.set(mat.entry(r, c2), g1);
266 }
267 }
268
269 // dot product of *columns* i,j
270 static void dot_product(const Mat& mat,
271 size_t i,
272 size_t j,
274 {
275 assert(i < mat.numColumns());
276 assert(j < mat.numColumns());
277
278 Element f(mat.ring());
279 mat.ring().set_zero(f);
280 mat.ring().set_zero(result);
281
282 for (size_t r = 0; r < mat.numRows(); ++r)
283 {
284 mat.ring().mult(f, mat.entry(r,i), mat.entry(r,j));
285 mat.ring().add(result, result, f);
286 }
287 }
288
289 static bool row_permute(Mat& mat, size_t start_row, M2_arrayint perm)
290 {
291 // We copy one row to another location for each cycle in 'perm' of length > 1
292 size_t nrows_to_permute = perm->len;
293 std::unique_ptr<bool[]> done(new bool[nrows_to_permute]);
294 for (size_t i = 0; i < nrows_to_permute; i++) done[i] = true;
295 // We check that this is a permutation
296 for (size_t i = 0; i < nrows_to_permute; i++)
297 {
298 size_t j = perm->array[i];
299 if (!done[j])
300 {
301 ERROR("expected permutation");
302 return false;
303 }
304 done[j] = false;
305 }
306 typename RT::ElementArray tmp(mat.ring(), mat.numColumns());
307 size_t next = 0;
308
309 while (next < nrows_to_permute)
310 {
311 if (done[next] || perm->array[next] == next)
312 {
313 next++;
314 }
315 else
316 {
317 // store row 'next' into tmp
318 for (int i=0; i<mat.numColumns(); ++i) std::swap(tmp[i], mat.entry(start_row + next, i));
319
320 size_t r = next;
321 while (perm->array[r] != next)
322 {
323 // copy row perm[r] to row r
324 for (int i = 0; i < mat.numColumns(); ++i)
325 std::swap(mat.entry(start_row + perm->array[r], i),
326 mat.entry(start_row + r, i));
327 done[r] = true;
328 r = perm->array[r];
329 }
330 // we swap tmp and r
331 for (int i=0; i<mat.numColumns(); ++i) std::swap(tmp[i], mat.entry(start_row + r, i));
332 done[r] = true;
333 }
334 }
335 return true;
336 }
337
338 static bool column_permute(Mat& mat, size_t start_col, M2_arrayint perm)
339 {
340 // We copy one col to another location for each cycle in 'perm' of length > 1
341 size_t ncols_to_permute = perm->len;
342 std::unique_ptr<bool[]> done(new bool[ncols_to_permute]);
343 for (size_t i = 0; i < ncols_to_permute; i++) done[i] = true;
344 // We check that this is a permutation
345 for (size_t i = 0; i < ncols_to_permute; i++)
346 {
347 size_t j = perm->array[i];
348 if (!done[j])
349 {
350 ERROR("expected permutation");
351 return false;
352 }
353 done[j] = false;
354 }
355 typename RT::ElementArray tmp(mat.ring(), mat.numRows());
356 size_t next = 0;
357
358 while (next < ncols_to_permute)
359 {
360 if (done[next] || perm->array[next] == next)
361 {
362 next++;
363 }
364 else
365 {
366 // store col 'next' into tmp
367 for (int i=0; i<mat.numRows(); ++i) std::swap(tmp[i], mat.entry(i, start_col + next));
368
369 size_t c = next;
370 while (perm->array[c] != next)
371 {
372 // swap col perm[c] to col c
373 for (int i = 0; i < mat.numRows(); ++i)
374 std::swap(mat.entry(i, start_col + perm->array[c]),
375 mat.entry(i, start_col + c));
376 done[c] = true;
377 c = perm->array[c];
378 }
379 // we swap tmp and c
380 for (int i=0; i<mat.numRows(); ++i) std::swap(tmp[i], mat.entry(i, start_col + c));
381 done[c] = true;
382 }
383 }
384 return true;
385 }
386
387 static void insert_columns(Mat& mat, size_t i, size_t n_to_add)
388 /* Insert n_to_add columns directly BEFORE column i. TODO: use iterators */
389 {
390 size_t new_ncols = mat.numColumns() + n_to_add;
391 Mat newMatrix(mat.ring(), mat.numRows(), new_ncols);
392
393 for (size_t r = 0; r < mat.numRows(); r++)
394 {
395 for (size_t c = 0; c < i; c++)
396 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c));
397 for (size_t c = i; c < mat.numColumns(); c++)
398 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c + n_to_add));
399 }
400 mat.swap(newMatrix);
401 }
402
403 static void insert_rows(Mat& mat, size_t i, size_t n_to_add)
404 /* Insert n_to_add rows directly BEFORE row i. TODO: use iterators */
405 {
406 size_t new_nrows = mat.numRows() + n_to_add;
407 Mat newMatrix(mat.ring(), new_nrows, mat.numColumns());
408
409 for (size_t c = 0; c < mat.numColumns(); c++)
410 {
411 for (size_t r = 0; r < i; r++)
412 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c));
413 for (size_t r = i; r < mat.numRows(); r++)
414 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r + n_to_add, c));
415 }
416 mat.swap(newMatrix);
417 }
418
419 static void delete_columns(Mat& mat, size_t i, size_t j)
420 /* Delete columns i .. j from M. TODO: use iterators */
421 {
422 assert(i < mat.numColumns());
423 assert(j < mat.numColumns());
424 assert(i <= j);
425 size_t n_to_delete = j - i + 1;
426 size_t new_ncols = mat.numColumns() - n_to_delete;
427 Mat newMatrix(mat.ring(), mat.numRows(), new_ncols);
428
429 for (size_t r = 0; r < mat.numRows(); r++)
430 {
431 for (size_t c = 0; c < i; c++)
432 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c));
433 for (size_t c = j + 1; c < mat.numColumns(); c++)
434 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c - n_to_delete));
435 }
436 mat.swap(newMatrix);
437 }
438
439 static void delete_rows(Mat& mat, size_t i, size_t j)
440 /* Delete rows i .. j from M. TODO: use iterators */
441 {
442 assert(i < mat.numRows());
443 assert(j < mat.numRows());
444 assert(i <= j);
445 size_t n_to_delete = j - i + 1;
446 size_t new_nrows = mat.numRows() - n_to_delete;
447 Mat newMatrix(mat.ring(), new_nrows, mat.numColumns());
448
449 for (size_t c = 0; c < mat.numColumns(); c++)
450 {
451 for (size_t r = 0; r < i; r++)
452 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r, c));
453 for (size_t r = j + 1; r < mat.numRows(); r++)
454 mat.ring().swap(mat.entry(r, c), newMatrix.entry(r - n_to_delete, c));
455 }
456 mat.swap(newMatrix);
457 }
458
460 // reduce_by_pivots /////////
462 private:
463 // An internal function for reduceby_pivots
464 static void perform_reduction(Mat& M,
465 size_t r,
466 size_t c,
467 size_t nr,
468 size_t nc,
469 int pivot_type)
470 // Subroutine of reduce_pivots()
471 // pivot_type: 1 means pivot is 1, -1 means pivot is -1, 0 means pivot is unit
472 {
473 // Flip rows r, nr
474 // Flip cols c, nc
475 // Use (nr,nc) location to remove all terms in columns 0..nc-1
476 // and in row nr.
477 // Replace column nc with all zeros, except 1 in nr row.
478
479 Element pivot(M.ring()), coef(M.ring()), f(M.ring()), zero(M.ring()),
480 one(M.ring());
481 M.ring().set_from_long(zero, 0);
482 M.ring().set_from_long(one, 1);
483
484 interchange_columns(M, c, nc);
485 interchange_rows(M, r, nr);
486 long pivotrow = lead_row(M, nc, pivot);
487 if (pivot_type == -1) // pivot is -1
488 scale_column(M, nc, pivot);
489 else if (pivot_type == 0)
490 divide_column(M, nc, pivot);
491 for (int i = 0; i < nc; i++)
492 {
493 pivotrow = lead_row(M, i, coef);
494 if (pivotrow < 0) continue;
495 if (pivotrow == nr)
496 {
497 // Do the reduction
498 M.ring().negate(f, coef);
499 column_op(M, i, f, nc);
500 }
501 }
502
503 scale_column(M, nc, zero);
504 setEntry(M, nr, nc, one);
505 }
506
507 public:
508 static void reduce_by_pivots(Mat& M)
509 {
510 if (M.numRows() == 0 or M.numColumns() == 0) return;
511 size_t nr = M.numRows() - 1;
512 size_t nc = M.numColumns() - 1;
513
514 Element one(M.ring()), minus_one(M.ring());
515 M.ring().set_from_long(one, 1);
516 M.ring().set_from_long(minus_one, -1);
517
518 // After using the pivot element, it is moved to [nrows-1,ncols-1]
519 // and nrows and ncols are decremented.
520
521 for (size_t i = 0; i <= nc; i++)
522 {
523 for (size_t j = 0; j < M.numRows(); ++j)
524 {
525 auto& p = M.entry(j,i);
526 if (M.ring().is_zero(p)) continue;
527 int pivot_type = 0;
528 if (M.ring().is_equal(one, p))
529 pivot_type = 1;
530 else if (M.ring().is_equal(minus_one, p))
531 pivot_type = -1;
532 if (pivot_type != 0)
533 {
534 // printf("before reduction: j=%lu i=%lu:\n",j,i);
535 // displayMat(M);
536 perform_reduction(M, j, i, nr--, nc--, pivot_type);
537 // printf("after reduction: j=%lu i=%lu:\n",j,i);
538 // displayMat(M);
539 if (nr == static_cast<size_t>(-1) or
540 nc == static_cast<size_t>(-1))
541 return;
542 // restart loop with the (new) column i
543 i = -1;
544 break;
545 }
546 }
547 }
548
549 // Now search for other possible pivots
550 for (size_t i = 0; i <= nc; i++)
551 {
552 for (size_t j = 0; j < M.numRows(); ++j)
553 {
554 auto& p = M.entry(j,i);
555 if (M.ring().is_zero(p)) continue;
556 if (!M.ring().is_unit(p)) continue;
557 int pivot_type = 0;
558 if (M.ring().is_equal(one, p))
559 pivot_type = 1;
560 else if (M.ring().is_equal(minus_one, p))
561 pivot_type = -1;
562
563 // printf("before general reduction: j=%lu i=%lu:\n",j,i);
564 // displayMat(M);
565 perform_reduction(M, j, i, nr--, nc--, pivot_type);
566 // printf("after general reduction: j=%lu i=%lu:\n",j,i);
567 // displayMat(M);
568 if (nr == static_cast<size_t>(-1) or nc == static_cast<size_t>(-1))
569 return;
570 // restart loop with the (new) column i
571 i = -1;
572 break;
573 }
574 }
575 }
576
577
578 static void setFromSubmatrix(const Mat& mat,
579 size_t r0,
580 size_t r1,
581 size_t c0,
582 size_t c1,
583 Mat& result)
584 /* Set 'result' with the given submatrix of 'mat'. TODO: use iterator on
585 * result */
586 {
587 // assert(r1-r0+1<=result.numRows());
588 // assert(c1-c0+1<=result.numColumns());
589 for (size_t r = r0; r <= r1; r++)
590 for (size_t c = c0; c <= c1; c++)
591 mat.ring().set(result.entry(r - r0, c - c0), mat.entry(r, c));
592 }
593
594 static void setFromSubmatrix(const Mat& mat,
595 M2_arrayint rows,
596 M2_arrayint cols,
597 Mat& result)
598 /* Set 'result' with the given submatrix of 'mat'. TODO: use iterator on
599 * result */
600 {
601 result.resize(rows->len, cols->len); // resets to a zero matrix
602 for (size_t r = 0; r < rows->len; r++)
603 for (size_t c = 0; c < cols->len; c++)
604 mat.ring().set(result.entry(r, c),
605 mat.entry(rows->array[r], cols->array[c]));
606 }
607
608 static void setFromSubmatrix(const Mat& mat, M2_arrayint cols, Mat& result)
609 /* Set 'result' with the given submatrix of 'mat'. TODO: use iterator on
610 * result */
611 {
612 result.resize(mat.numRows(), cols->len); // resets to a zero matrix
613 for (size_t r = 0; r < mat.numRows(); r++)
614 for (size_t c = 0; c < cols->len; c++)
615 mat.ring().set(result.entry(r, c), mat.entry(r, cols->array[c]));
616 }
617
618 static void getEntry(const Mat& mat, size_t r, size_t c, ElementType& result)
619 {
620 mat.ring().set(result, mat.entry(r, c));
621 }
622
623 static void setEntry(Mat& mat, size_t r, size_t c, const ElementType& a)
624 {
625 mat.ring().set(mat.entry(r, c), a);
626 }
627
628 private:
629#if 0
630 // MES June 2013: working on this code
631 // Internal function for reduceByPivots
632 static void perform_reduction(Mat& M,
633 size_t r, size_t c,
634 size_t nr, size_t nc,
635 int pivot_type)
636 // Subroutine of reduceByPivots()
637 // pivot_type: 1 means pivot is 1, -1 means pivot is -1, 0 means pivot is unit
638 {
639 // Swap rows r, nr
640 // Swap cols c, nc
641 // Use (nr,nc) location to remove all terms in columns 0..nc-1
642 // and in row nr.
643 // Replace column nc with all zeros, except 1 in nr row.
644 const Ring *R = M->get_ring();
645 M->interchange_columns(c,nc);
646 M->interchange_rows(r,nr);
647 ring_elem pivot;
648 long pivotrow = M->lead_row(nc, pivot);
649 if (pivot_type == -1) // pivot is -1
650 M->scale_column(nc,pivot);
651 else if (pivot_type == 0)
652 M->divide_column(nc, pivot);
653 for (int i=0; i<nc; i++)
654 {
655 ring_elem coef;
656 pivotrow = M->lead_row(i,coef);
657 if (pivotrow < 0) continue;
658 if (pivotrow == nr)
659 {
660 // Do the reduction
661 // M.ring().negate(M.entry(pivotrow, i));
662 ring_elem f = R->negate(coef);
663 M->column_op(i, f, nc);
664 }
665 }
666 M->scale_column(nc, R->zero());
667 M->set_entry(nr,nc,R->one());
668 }
669
670 static void reduceByPivots(Mat& M)
671 {
672 if (M.numRows() == 0 or M.numColumns() == 0) return;
673 size_t nr = M.numRows()-1;
674 size_t nc = M.numColumns()-1;
675
676 const Ring *K = M->get_ring();
677 ring_elem one = K->one();
678 ring_elem minus_one = K->minus_one();
679
680 // After using the pivot element, it is moved to [nrows-1,ncols-1]
681 // and nrows and ncols are decremented.
682
683 MutableMatrix::iterator *p = M->begin();
684 for (int i=0; i<=nc; i++)
685 {
686 p->set(i);
687 for (; p->valid(); p->next())
688 {
689 int pivot_type = 0;
690 ring_elem coef;
691 p->copy_ring_elem(coef);
692 if (K->is_equal(one, coef))
693 pivot_type = 1;
694 else if (K->is_equal(minus_one, coef))
695 pivot_type = -1;
696 if (pivot_type != 0)
697 {
698 perform_reduction(M, static_cast<int>(p->row()), i, nr, nc, pivot_type);
699 if (nr == 0 or nc == 0) return;
700 --nr;
701 --nc;
702 // restart loop with the (new) column i
703 i = -1;
704 break;
705 }
706 }
707 }
708
709 // Now search for other possible pivots
710 for (int i=0; i<=nc; i++)
711 {
712 p->set(i);
713 for (; p->valid(); p->next())
714 {
715 ring_elem coef;
716 p->copy_ring_elem(coef);
717 if (!K->is_unit(coef)) continue;
718 int pivot_type = 0;
719 if (K->is_equal(one, coef))
720 pivot_type = 1;
721 else if (K->is_equal(minus_one, coef))
722 pivot_type = -1;
723
724 perform_reduction(M, static_cast<int>(p->row()), i, nr, nc, pivot_type);
725 if (nr == 0 or nc == 0) return;
726 --nr;
727 --nc;
728 // restart loop with the (new) column i
729 i = -1;
730 break;
731 }
732 }
733}
734#endif
735};
736
737template <typename RT>
739{
740 public:
741 typedef SMat<RT> Mat;
743
744 static size_t lead_row(const Mat& mat, size_t col)
745 /* returns the largest index row which has a non-zero value in column 'col'.
746 returns -1 if the column is 0 */
747 {
748 return mat.lead_row(col);
749 }
750
751 static size_t lead_row(const Mat& mat, size_t col, ElementType& result)
752 /* returns the largest index row which has a non-zero value in column 'col'.
753 Also sets result to be the entry at this index.
754 returns -1 if the column is 0, or if col is out of range
755 No error is flagged. */
756 {
757 return mat.lead_row(col, result);
758 }
759
760 // Row and column operations //
762 // The following routines return false if one of the row or columns given
763 // is out of range.
764
765 static void interchange_rows(Mat& mat, size_t i, size_t j)
766 /* swap rows: row(i) <--> row(j) */ { mat.interchange_rows(i, j); }
767 static void interchange_columns(Mat& mat, size_t i, size_t j)
768 /* swap columns: column(i) <--> column(j) */
769 {
770 mat.interchange_columns(i, j);
771 }
772 static void scale_row(Mat& mat, size_t i, const ElementType& r)
773 /* row(i) <- r * row(i) */ { mat.scale_row(i, r); }
774 static void scale_column(Mat& mat, size_t i, const ElementType& r)
775 /* column(i) <- r * column(i) */ { mat.scale_column(i, r); }
776 static void divide_row(Mat& mat, size_t i, const ElementType& r)
777 /* row(i) <- row(i) / r */ { mat.divide_row(i, r); }
778 static void divide_column(Mat& mat, size_t i, const ElementType& r)
779 /* column(i) <- column(i) / r */ { mat.divide_column(i, r); }
780 static void row_op(Mat& mat, size_t i, const ElementType& r, size_t j)
781 /* row(i) <- row(i) + r * row(j) */ { mat.row_op(i, r, j); }
782 static void column_op(Mat& mat, size_t i, const ElementType& r, size_t j)
783 /* column(i) <- column(i) + r * column(j) */ { mat.column_op(i, r, j); }
784 static void column2by2(Mat& mat,
785 size_t c1,
786 size_t c2,
787 const ElementType& a1,
788 const ElementType& a2,
789 const ElementType& b1,
790 const ElementType& b2)
791 /* column(c1) <- a1 * column(c1) + a2 * column(c2),
792 column(c2) <- b1 * column(c1) + b2 * column(c2)
793 */
794 {
795 mat.column2by2(c1, c2, a1, a2, b1, b2);
796 }
797
798 static void row2by2(Mat& mat,
799 size_t r1,
800 size_t r2,
801 const ElementType& a1,
802 const ElementType& a2,
803 const ElementType& b1,
804 const ElementType& b2)
805 /* row(r1) <- a1 * row(r1) + a2 * row(r2),
806 row(r2) <- b1 * row(r1) + b2 * row(r2)
807 */
808 {
809 mat.row2by2(r1, r2, a1, a2, b1, b2);
810 }
811
812 static void dot_product(const Mat& mat,
813 size_t i,
814 size_t j,
816 {
817 mat.dot_product(i, j, result);
818 }
819
820 static bool row_permute(Mat& mat, size_t start_row, M2_arrayint perm)
821 {
822 return mat.row_permute(start_row, perm);
823 }
824
825 static bool column_permute(Mat& mat, size_t start_col, M2_arrayint perm)
826 {
827 return mat.column_permute(start_col, perm);
828 }
829
830 static void insert_columns(Mat& mat, size_t i, size_t n_to_add)
831 /* Insert n_to_add columns directly BEFORE column i. */
832 {
833 mat.insert_columns(i, n_to_add);
834 }
835
836 static void insert_rows(Mat& mat, size_t i, size_t n_to_add)
837 /* Insert n_to_add rows directly BEFORE row i. */
838 {
839 mat.insert_rows(i, n_to_add);
840 }
841
842 static void delete_columns(Mat& mat, size_t i, size_t j)
843 /* Delete columns i .. j from M */ { mat.delete_columns(i, j); }
844 static void delete_rows(Mat& mat, size_t i, size_t j)
845 /* Delete rows i .. j from M */ { mat.delete_rows(i, j); }
846 static void reduce_by_pivots(Mat& M)
847 {
848 (void) M;
849 throw exc::engine_error(
850 "reduce_py_pivots not yet implemented for sparse mutable matrices");
851 // TODO: write this!!
852 }
853
854 static void setFromSubmatrix(const Mat& mat,
855 M2_arrayint rows,
856 M2_arrayint cols,
857 Mat& result)
858 /* Set 'result' with the given submatrix of 'mat' */
859 {
860 result.setFromSubmatrix(mat, rows, cols);
861 }
862
863 static void setFromSubmatrix(const Mat& mat, M2_arrayint cols, Mat& result)
864 /* Set 'result' with the given submatrix of 'mat' */
865 {
866 result.setFromSubmatrix(mat, cols);
867 }
868
869 static void getEntry(const Mat& mat, size_t r, size_t c, ElementType& result)
870 {
871 mat.get_entry(r, c, result);
872 }
873
874 static void setEntry(Mat& mat, size_t r, size_t c, const ElementType& a)
875 {
876 mat.set_entry(r, c, a);
877 }
878};
879
880#endif
881
882// Local Variables:
883// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
884// indent-tabs-mode: nil
885// End:
size_t numRows() const
Definition dmat.hpp:144
ElementType & entry(size_t row, size_t column)
Definition dmat.hpp:148
const ACoeffRing & ring() const
Definition dmat.hpp:143
void swap(DMat< ACoeffRing > &M)
Definition dmat.hpp:134
RT::ElementType ElementType
Definition dmat.hpp:65
size_t numColumns() const
Definition dmat.hpp:145
Definition dmat.hpp:62
static void setEntry(Mat &mat, size_t r, size_t c, const ElementType &a)
static void scale_row(Mat &mat, size_t i, const ElementType &a)
static void insert_columns(Mat &mat, size_t i, size_t n_to_add)
static void setFromSubmatrix(const Mat &mat, M2_arrayint rows, M2_arrayint cols, Mat &result)
static void divide_row(Mat &mat, size_t i, const ElementType &a)
static void scale_column(Mat &mat, size_t i, const ElementType &a)
static void setFromSubmatrix(const Mat &mat, M2_arrayint cols, Mat &result)
static void column_op(Mat &mat, size_t i, const ElementType &a, size_t j)
static void interchange_columns(Mat &mat, size_t i, size_t j)
static void dot_product(const Mat &mat, size_t i, size_t j, ElementType &result)
static void insert_rows(Mat &mat, size_t i, size_t n_to_add)
static size_t lead_row(const Mat &mat, size_t col)
static void delete_columns(Mat &mat, size_t i, size_t j)
static void perform_reduction(Mat &M, size_t r, size_t c, size_t nr, size_t nc, int pivot_type)
static void delete_rows(Mat &mat, size_t i, size_t j)
static size_t lead_row(const Mat &mat, size_t col, ElementType &result)
static void interchange_rows(Mat &mat, size_t i, size_t j)
static bool column_permute(Mat &mat, size_t start_col, M2_arrayint perm)
static void column2by2(Mat &mat, size_t c1, size_t c2, const ElementType &a1, const ElementType &a2, const ElementType &b1, const ElementType &b2)
static void setFromSubmatrix(const Mat &mat, size_t r0, size_t r1, size_t c0, size_t c1, Mat &result)
static void row2by2(Mat &mat, size_t r1, size_t r2, const ElementType &a1, const ElementType &a2, const ElementType &b1, const ElementType &b2)
static void reduce_by_pivots(Mat &M)
static void getEntry(const Mat &mat, size_t r, size_t c, ElementType &result)
static void row_op(Mat &mat, size_t i, const ElementType &a, size_t j)
static void divide_column(Mat &mat, size_t i, const ElementType &a)
static bool row_permute(Mat &mat, size_t start_row, M2_arrayint perm)
static void column_op(Mat &mat, size_t i, const ElementType &r, size_t j)
static void insert_columns(Mat &mat, size_t i, size_t n_to_add)
static void scale_row(Mat &mat, size_t i, const ElementType &r)
static void interchange_columns(Mat &mat, size_t i, size_t j)
static void divide_row(Mat &mat, size_t i, const ElementType &r)
static void column2by2(Mat &mat, size_t c1, size_t c2, const ElementType &a1, const ElementType &a2, const ElementType &b1, const ElementType &b2)
static void setEntry(Mat &mat, size_t r, size_t c, const ElementType &a)
static void getEntry(const Mat &mat, size_t r, size_t c, ElementType &result)
static bool row_permute(Mat &mat, size_t start_row, M2_arrayint perm)
static size_t lead_row(const Mat &mat, size_t col, ElementType &result)
static void setFromSubmatrix(const Mat &mat, M2_arrayint rows, M2_arrayint cols, Mat &result)
static void dot_product(const Mat &mat, size_t i, size_t j, ElementType &result)
static void delete_rows(Mat &mat, size_t i, size_t j)
static void delete_columns(Mat &mat, size_t i, size_t j)
static void setFromSubmatrix(const Mat &mat, M2_arrayint cols, Mat &result)
static bool column_permute(Mat &mat, size_t start_col, M2_arrayint perm)
static void row2by2(Mat &mat, size_t r1, size_t r2, const ElementType &a1, const ElementType &a2, const ElementType &b1, const ElementType &b2)
static size_t lead_row(const Mat &mat, size_t col)
static void insert_rows(Mat &mat, size_t i, size_t n_to_add)
static void row_op(Mat &mat, size_t i, const ElementType &r, size_t j)
static void scale_column(Mat &mat, size_t i, const ElementType &r)
static void divide_column(Mat &mat, size_t i, const ElementType &r)
static void interchange_rows(Mat &mat, size_t i, size_t j)
static void reduce_by_pivots(Mat &M)
virtual bool is_unit(const ring_elem f) const =0
ring_elem one() const
Definition ring.hpp:357
virtual bool is_equal(const ring_elem f, const ring_elem g) const =0
ring_elem zero() const
Definition ring.hpp:359
ring_elem minus_one() const
Definition ring.hpp:358
virtual ring_elem negate(const ring_elem f) const =0
xxx xxx xxx
Definition ring.hpp:102
void set_entry(size_t r, size_t c, const elem a)
Definition smat.hpp:903
void interchange_rows(size_t i, size_t j)
Definition smat.hpp:909
void insert_columns(size_t i, size_t n_to_add)
Definition smat.hpp:1059
void delete_columns(size_t i, size_t j)
Definition smat.hpp:1082
bool row_permute(size_t start_row, M2_arrayint perm)
Definition smat.hpp:1010
void divide_row(size_t i, elem r)
Definition smat.hpp:935
void interchange_columns(size_t i, size_t j)
Definition smat.hpp:916
size_t lead_row(size_t col) const
Definition smat.hpp:868
void column2by2(size_t c1, size_t c2, elem a1, elem a2, elem b1, elem b2)
Definition smat.hpp:974
void delete_rows(size_t i, size_t j)
Definition smat.hpp:1099
void scale_column(size_t i, elem r)
Definition smat.hpp:932
void row_op(size_t i, elem r, size_t j)
Definition smat.hpp:945
void row2by2(size_t r1, size_t r2, elem a1, elem a2, elem b1, elem b2)
Definition smat.hpp:959
void scale_row(size_t i, elem r)
Definition smat.hpp:925
bool get_entry(size_t r, size_t c, elem &result) const
Definition smat.hpp:895
void column_op(size_t i, elem r, size_t j)
Definition smat.hpp:952
void divide_column(size_t i, elem r)
Definition smat.hpp:942
bool column_permute(size_t start_col, M2_arrayint perm)
Definition smat.hpp:1032
CoeffRing::elem ElementType
Definition smat.hpp:49
void insert_rows(size_t i, size_t n_to_add)
Definition smat.hpp:1074
void dot_product(size_t i, size_t j, elem &result) const
Definition smat.hpp:1004
Definition smat.hpp:43
int minus_one
int p
int zero
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition mpreal.h:3244