Macaulay2 Engine
Loading...
Searching...
No Matches
smat.hpp
Go to the documentation of this file.
1// Copyright 2005 Michael E. Stillman
2
3#ifndef _smat_hpp_
4#define _smat_hpp_
5
32
33union ring_elem;
34#include "ZZp.hpp"
35
36class MutableMatrix;
37
38template <typename MT>
40
41template <typename ACoeffRing>
42class SMat : public our_new_delete
43{
44 // typedef typename EigenvalueType<ACoeffRing>::Ring EigenvalueRing;
45 // typedef SparseMatrixLinAlg<ACoeffRing> LinAlg;
46 // typedef SparseMatrixArithmetic<CoeffRing> Arithmetic;
47 public:
48 typedef ACoeffRing CoeffRing;
49 typedef typename CoeffRing::elem ElementType;
50 typedef ElementType
51 elem; // same as ElementType. Will possibly remove 'elem' later.
52 typedef typename CoeffRing::Element Element;
53 // typedef SMat<EigenvalueRing> EigenvalueMatrixType;
54
55 private:
56 struct sparsevec : public our_new_delete
57 {
59 size_t row;
61 };
62
63 friend class MatElementaryOps<SMat>;
64 const sparsevec *column(size_t c) const
65 {
66 assert(c < numColumns());
67 return columns_[c];
68 }
69 sparsevec *column(size_t c)
70 {
71 assert(c < numColumns());
72 return columns_[c];
73 }
74
75 public:
76 SMat() : coeffR(0), nrows_(0), ncols_(0), columns_(0) {} // Makes a zero
77 // matrix
78 SMat(const CoeffRing &coeffR0,
79 size_t nrows,
80 size_t ncols); // Makes a zero matrix
81
83 size_t nrows,
84 size_t ncols); // Makes a zero matrix, same ring.
85
86 SMat(const SMat<ACoeffRing> &M); // Copies (clones) M
87
88 virtual ~SMat()
89 {
90 for (size_t c = 0; c < ncols_; c++) { vec_remove(columns_[c]); }
92 }
93
94 void grab(SMat *M); // swaps M and this.
95
97
98 bool is_dense() const { return false; }
99 size_t numRows() const { return nrows_; }
100 size_t numColumns() const { return ncols_; }
101 // size_t n_rows() const { return nrows_; }
102 // size_t n_cols() const { return ncols_; }
103
104 const CoeffRing &ring() const { return *coeffR; }
105 void initialize(size_t nrows, size_t ncols, sparsevec **cols);
106 // void resize(size_t nrows, size_t ncols);
107
109 {
111 size_t col;
113
114 public:
115 void set(size_t col0)
116 {
117 col = col0;
118 v = M->columns_[col];
119 }
120 iterator(const SMat<CoeffRing> *M0) : M(M0), col(-1), v(0) {}
121 const elem &value() { return v->coeff; }
122 void next() { v = v->next; }
123 bool valid() { return v != 0; }
124 size_t row() { return v->row; }
126 {
127 M->ring().to_ring_elem(result, value());
128 }
129 };
130
131 iterator begin() const { return iterator(this); }
132 public:
133 size_t lead_row(size_t col) const;
134 /* returns the largest index row which has a non-zero value in column 'col'.
135 returns -1 if the column is 0 */
136
137 size_t lead_row(size_t col, elem &result) const;
138 /* returns the largest index row which has a non-zero value in column 'col'.
139 Also sets result to be the entry at this index.
140 returns -1 if the column is 0, or if col is out of range
141 No error is flagged. */
142
144 // Row and column operations //
146 // The following routines return false if one of the row or columns given
147 // is out of range.
148
149 bool get_entry(size_t r, size_t c, elem &result) const;
150 // Returns false if (r,c) is out of range or if result is 0. No error
151 // is returned. result <-- this(r,c), and is set to zero if false is returned.
152
153 void set_entry(size_t r, size_t c, const elem a);
154 // Returns false if (r,c) is out of range, or the ring of a is wrong.
155
156 void interchange_rows(size_t i, size_t j);
157 /* swap rows: row(i) <--> row(j) */
158
159 void interchange_columns(size_t i, size_t j);
160 /* swap columns: column(i) <--> column(j) */
161
162 void scale_row(size_t i, elem r);
163 /* row(i) <- r * row(i) */
164
165 void scale_column(size_t i, elem r);
166 /* column(i) <- r * column(i) */
167
168 void divide_row(size_t i, elem r);
169 /* row(i) <- row(i) / r */
170
171 void divide_column(size_t i, elem r);
172 /* column(i) <- column(i) / r */
173
174 void row_op(size_t i, elem r, size_t j);
175 /* row(i) <- row(i) + r * row(j) */
176
177 void column_op(size_t i, elem r, size_t j);
178 /* column(i) <- column(i) + r * column(j) */
179
180 void column2by2(size_t c1, size_t c2, elem a1, elem a2, elem b1, elem b2);
181 /* column(c1) <- a1 * column(c1) + a2 * column(c2),
182 column(c2) <- b1 * column(c1) + b2 * column(c2)
183 */
184
185 void row2by2(size_t r1, size_t r2, elem a1, elem a2, elem b1, elem b2);
186 /* row(r1) <- a1 * row(r1) + a2 * row(r2),
187 row(r2) <- b1 * row(r1) + b2 * row(r2)
188 */
189
190 void dot_product(size_t i, size_t j, elem &result) const;
191
192 bool row_permute(size_t start_row, M2_arrayint perm);
193
194 bool column_permute(size_t start_col, M2_arrayint perm);
195
196 void insert_columns(size_t i, size_t n_to_add);
197 /* Insert n_to_add columns directly BEFORE column i. */
198
199 void insert_rows(size_t i, size_t n_to_add);
200 /* Insert n_to_add rows directly BEFORE row i. */
201
202 void delete_columns(size_t i, size_t j);
203 /* Delete columns i .. j from M */
204
205 void delete_rows(size_t i, size_t j);
206 /* Delete rows i .. j from M */
207
208 bool is_zero() const;
209
210 bool is_equal(const SMat &B) const;
211
212 // this += B, assertion failure on bad ring or bad sizes
213 void addInPlace(const SMat &B);
214
215 // this -= B, assertion failure on bad ring or bad sizes
216 void subtractInPlace(const SMat &B);
217
218 // this = -this
220
221 // this = f * this
222 void scalarMultInPlace(const elem &f);
223
224 void setFromSubmatrix(const SMat &A, M2_arrayint rows, M2_arrayint cols);
225
226 void setFromSubmatrix(const SMat &A, M2_arrayint cols);
227
228 private:
229 const Ring *R; // To interface to the outside world
230 const CoeffRing
231 *coeffR; // Same as R, optimized for speed. R->get_CoeffRing()
232 size_t nrows_;
233 size_t ncols_;
234 sparsevec **columns_; // array has length ncols
235 // columns stored one after another
236
238 // sparsevec routines //
240 sparsevec *vec_new() const;
241 void vec_remove_node(sparsevec *&v) const;
242 void vec_remove(sparsevec *&v) const;
243 sparsevec *vec_copy(const sparsevec *v) const;
244 bool vec_equals(const sparsevec *v, const sparsevec *w) const;
245 bool vec_get_entry(const sparsevec *v, size_t r, elem &result) const;
246 void vec_set_entry(sparsevec *&v, size_t r, const elem &result) const;
247 void vec_interchange_rows(sparsevec *&v, size_t r1, size_t r2) const;
248 void vec_negate(sparsevec *&v) const;
249 void vec_scale_row(sparsevec *&v, size_t r, const elem &a) const;
250 void vec_scale(sparsevec *&v, const elem &a) const;
251 void vec_divide_row(sparsevec *&v, size_t r, const elem &a) const;
252 void vec_divide(sparsevec *&v, const elem &a) const;
253 void vec_add_to(sparsevec *&v, sparsevec *&w) const;
254 // v := v+w, w := 0
255 void vec_row_op(sparsevec *&v, size_t r1, const elem &a, size_t r2) const;
256 // row(r1 in v) := row(r1 in v) + a * row(r2 in v)
257 void vec_row_op2(sparsevec *&v,
258 size_t r1,
259 size_t r2,
260 const elem &a1,
261 const elem &a2,
262 const elem &b1,
263 const elem &b2) const;
264 // row(r1 in v) := a1 * row(r1 in v) + a2 * row(r2 in v)
265 // row(r2 in v) := b1 * row(r1 in v) + b2 * row(r2 in v) (RHS refers to
266 // previous values)
267 void vec_column_op(sparsevec *&v, const elem &a, sparsevec *w) const;
268 // v := v + a*w
269 void vec_dot_product(sparsevec *v, sparsevec *w, elem &result) const;
270 void vec_sort(sparsevec *&v) const;
271 void vec_permute(sparsevec *&v, size_t start_row, M2_arrayint perm) const;
272 void vec_insert_rows(sparsevec *&v, size_t i, size_t n_to_add) const;
273 void vec_delete_rows(sparsevec *&v, size_t i, size_t j) const;
274};
275
277// sparsevec operations //
279
280template <typename CoeffRing>
282{
283 return new sparsevec;
284}
285
286template <typename CoeffRing>
288{
289 ring().clear(v->coeff);
290 delete v;
291}
292
293template <typename CoeffRing>
295{
296 while (v != 0)
297 {
298 sparsevec *tmp = v;
299 v = v->next;
300 vec_remove_node(tmp);
301 }
302}
303
304template <typename CoeffRing>
306 const sparsevec *v) const
307{
308 sparsevec head;
309 sparsevec *result = &head;
310 for (const sparsevec *p = v; p != 0; p = p->next)
311 {
312 sparsevec *w = vec_new();
313 result->next = w;
314 result = w;
315 w->row = p->row;
316 ring().init_set(w->coeff, p->coeff);
317 }
318 result->next = 0;
319 return head.next;
320}
321
322template <typename CoeffRing>
323bool SMat<CoeffRing>::vec_equals(const sparsevec *v, const sparsevec *w) const
324{
325 for (; v != NULL && w != NULL; v = v->next, w = w->next)
326 if (!ring().is_equal(v->coeff, w->coeff)) return false;
327 return true;
328}
329
330template <typename CoeffRing>
332 size_t r,
333 elem &result) const
334{
335 for (const sparsevec *p = v; p != 0; p = p->next)
336 if (p->row < r)
337 break;
338 else if (p->row == r)
339 {
340 ring().set(result, p->coeff);
341 return true;
342 }
343 return false;
344}
345
346template <typename CoeffRing>
348 size_t r,
349 const elem &a) const
350{
351 sparsevec *p;
352 bool iszero = ring().is_zero(a);
353 sparsevec head;
354 head.next = v;
355 for (p = &head; p->next != 0; p = p->next)
356 if (p->next->row <= r) break;
357
358 if (p->next == 0 || p->next->row < r)
359 {
360 if (iszero) return;
361 sparsevec *w = vec_new();
362 w->next = p->next;
363 w->row = r;
364 ring().init_set(w->coeff, a);
365 p->next = w;
366 }
367 else if (p->next->row == r)
368 {
369 if (iszero)
370 {
371 // delete node
372 sparsevec *tmp = p->next;
373 p->next = tmp->next;
374 vec_remove_node(tmp);
375 }
376 else
377 ring().set(p->next->coeff, a);
378 }
379 v = head.next;
380}
381
382template <typename CoeffRing>
384 size_t i,
385 size_t j) const
386{
387 sparsevec *p;
388 if (i == j) return;
389 if (v == 0) return;
390 if (i < j)
391 {
392 size_t tmp = i;
393 i = j;
394 j = tmp;
395 }
396 // So now i > j.
397 sparsevec head;
398 head.next = v;
399 sparsevec *vec1;
400 sparsevec *vec2;
401 for (p = &head; p->next != 0; p = p->next)
402 if (p->next->row <= i) break;
403 vec1 = p;
404 for (; p->next != 0; p = p->next)
405 if (p->next->row <= j) break;
406 vec2 = p;
407 if (vec1->next != 0 && vec1->next->row == i)
408 {
409 if (vec2->next != 0 && vec2->next->row == j)
410 {
411 std::swap(vec1->next->coeff, vec2->next->coeff);
412 return;
413 }
414 }
415 else if (vec2->next != 0 && vec2->next->row == j)
416 {
417 sparsevec *tmp = vec1;
418 vec1 = vec2;
419 vec2 = tmp;
420 j = i; // Used below.
421 }
422 else
423 return;
424
425 sparsevec *tmp = vec1->next;
426 if (vec2 != tmp)
427 {
428 vec1->next = tmp->next;
429 tmp->next = vec2->next;
430 vec2->next = tmp;
431 }
432 tmp->row = j;
433 v = head.next;
434}
435
436template <typename CoeffRing>
438 size_t r,
439 const elem &a) const
440{
441 sparsevec head;
442 head.next = v;
443 for (sparsevec *p = &head; p->next != 0; p = p->next)
444 if (p->next->row < r)
445 break;
446 else if (p->next->row == r)
447 {
448 ring().mult(p->next->coeff, a, p->next->coeff);
449 if (ring().is_zero(p->next->coeff))
450 {
451 sparsevec *tmp = p->next;
452 p->next = tmp->next;
453 vec_remove_node(tmp);
454 }
455 break;
456 }
457 v = head.next;
458}
459
460template <typename CoeffRing>
462{
463 if (ring().is_zero(a))
464 {
465 vec_remove(v);
466 v = 0;
467 return;
468 }
469 sparsevec head;
470 head.next = v;
471 for (sparsevec *p = &head; p->next != 0; p = p->next)
472 {
473 ring().mult(p->next->coeff, a, p->next->coeff);
474 if (ring().is_zero(p->next->coeff))
475 {
476 sparsevec *tmp = p->next;
477 p->next = tmp->next;
478 vec_remove_node(tmp);
479 if (p->next == 0) break;
480 }
481 }
482 v = head.next;
483}
484
485template <typename CoeffRing>
487{
488 for (sparsevec *p = v; p->next != NULL; p = p->next)
489 ring().negate(p->coeff, p->coeff);
490}
491
492template <typename CoeffRing>
494 size_t r,
495 const elem &a) const
496{
497 sparsevec head;
498 head.next = v;
499 for (sparsevec *p = &head; p->next != 0; p = p->next)
500 if (p->next->row < r)
501 break;
502 else if (p->next->row == r)
503 {
504 ring().divide(p->next->coeff, p->next->coeff, a);
505 if (ring().is_zero(p->next->coeff))
506 {
507 sparsevec *tmp = p->next;
508 p->next = tmp->next;
509 vec_remove_node(tmp);
510 }
511 break;
512 }
513 v = head.next;
514}
515
516template <typename CoeffRing>
518{
519 if (ring().is_zero(a))
520 {
521 vec_remove(v);
522 v = 0;
523 return;
524 }
525 sparsevec head;
526 head.next = v;
527 for (sparsevec *p = &head; p->next != 0; p = p->next)
528 {
529 ring().divide(p->next->coeff, p->next->coeff, a);
530 if (ring().is_zero(p->next->coeff))
531 {
532 sparsevec *tmp = p->next;
533 p->next = tmp->next;
534 vec_remove_node(tmp);
535 if (p->next == 0) break;
536 }
537 }
538 v = head.next;
539}
540
541template <typename CoeffRing>
543// v := v+w, w := 0
544{
545 if (w == 0) return;
546 if (v == 0)
547 {
548 v = w;
549 w = 0;
550 return;
551 }
552 sparsevec head;
553 sparsevec *result = &head;
554 while (true)
555 if (v->row < w->row)
556 {
557 result->next = w;
558 result = result->next;
559 w = w->next;
560 if (w == 0)
561 {
562 result->next = v;
563 v = head.next;
564 return;
565 }
566 }
567 else if (v->row > w->row)
568 {
569 result->next = v;
570 result = result->next;
571 v = v->next;
572 if (v == 0)
573 {
574 result->next = w;
575 v = head.next;
576 w = 0;
577 return;
578 }
579 }
580 else
581 {
582 sparsevec *tmv = v;
583 sparsevec *tmw = w;
584 v = v->next;
585 w = w->next;
586 ring().add(tmv->coeff, tmv->coeff, tmw->coeff);
587 if (ring().is_zero(tmv->coeff))
588 {
589 vec_remove_node(tmv);
590 }
591 else
592 {
593 result->next = tmv;
594 result = result->next;
595 }
596 vec_remove_node(tmw);
597 if (w == 0)
598 {
599 result->next = v;
600 v = head.next;
601 return;
602 }
603 if (v == 0)
604 {
605 result->next = w;
606 v = head.next;
607 w = 0;
608 return;
609 }
610 }
611}
612
613template <typename CoeffRing>
615 size_t r1,
616 const elem &a,
617 size_t r2) const
618// row(r1 in v) := row(r1 in v) + a * row(r2 in v)
619{
620 sparsevec *p;
621 sparsevec *vec2 = 0;
622 for (p = v; p != 0; p = p->next)
623 if (p->row == r2)
624 {
625 vec2 = p;
626 break;
627 }
628 if (vec2 == 0) return;
629 typename CoeffRing::Element c(ring());
630 ring().set_zero(c);
631 ring().mult(c, vec2->coeff, a);
632 if (ring().is_zero(c))
633 {
634 return; // nothing to change
635 }
636 // Now add c to the r1'th row of v
637 sparsevec head;
638 head.next = v;
639 for (p = &head; p->next != 0; p = p->next)
640 if (p->next->row <= r1) break;
641 if (p->next == 0 || p->next->row < r1)
642 {
643 // Make a new node
644 sparsevec *w = vec_new();
645 w->next = p->next;
646 w->row = r1;
647 ring().init_set(w->coeff, c);
648 p->next = w;
649 }
650 else
651 {
652 ring().add(p->next->coeff, p->next->coeff, c);
653 if (ring().is_zero(p->next->coeff))
654 {
655 sparsevec *tmp = p->next;
656 p->next = tmp->next;
657 vec_remove_node(tmp);
658 }
659 }
660 v = head.next;
661}
662
663template <typename CoeffRing>
665 size_t r1,
666 size_t r2,
667 const elem &a1,
668 const elem &a2,
669 const elem &b1,
670 const elem &b2) const
671// row(r1 in v) := a1 * row(r1 in v) + a2 * row(r2 in v)
672// row(r2 in v) := b1 * row(r1 in v) + b2 * row(r2 in v) (RHS refers to previous
673// values)
674{
675 // v[row r1] = a1 * v[r1] + a2 * v[r2]
676 // v[row r2] = b1 * v[r1] + b2 * v[r2]
677 Element e1(ring()), e2(ring()), c1(ring()), c2(ring()), c3(ring()),
678 c4(ring());
679
680 ring().set_zero(c1);
681 ring().set_zero(c2);
682 ring().set_zero(c3);
683 ring().set_zero(c4);
684 ring().set_zero(e1);
685 ring().set_zero(e2);
686 bool r1_nonzero = vec_get_entry(v, r1, e1);
687 bool r2_nonzero = vec_get_entry(v, r2, e2);
688 if (!r1_nonzero && !r2_nonzero)
689 {
690 return;
691 }
692 if (r1_nonzero)
693 {
694 ring().mult(c1, a1, e1);
695 ring().mult(c3, b1, e1);
696 }
697 if (r2_nonzero)
698 {
699 ring().mult(c2, a2, e2);
700 ring().mult(c4, b2, e2);
701 }
702
703 ring().add(c1, c1, c2);
704 ring().add(c3, c3, c4);
705 vec_set_entry(v, r1, c1);
706 vec_set_entry(v, r2, c3);
707}
708
709template <typename CoeffRing>
711 const elem &a,
712 sparsevec *w) const
713// v := v + a*w
714{
715 sparsevec *w1 = vec_copy(w);
716 vec_scale(w1, a);
717 vec_add_to(v, w1);
718}
719
720template <typename CoeffRing>
722 sparsevec *w,
723 elem &result) const
724{
725 Element a(ring());
726 ring().set_zero(a);
727 ring().set_zero(result);
728 while (true)
729 {
730 if (v == 0 || w == 0) break;
731 if (v->row > w->row)
732 v = v->next;
733 else if (v->row < w->row)
734 w = w->next;
735 else
736 {
737 ring().mult(a, v->coeff, w->coeff);
738 ring().add(result, result, a);
739 v = v->next;
740 w = w->next;
741 }
742 }
743}
744
745template <typename CoeffRing>
747{
748 if (f == 0 || f->next == 0) return;
749 sparsevec *f1 = 0;
750 sparsevec *f2 = 0;
751 while (f != 0)
752 {
753 sparsevec *t = f;
754 f = f->next;
755 t->next = f1;
756 f1 = t;
757
758 if (f == 0) break;
759 t = f;
760 f = f->next;
761 t->next = f2;
762 f2 = t;
763 }
764
765 vec_sort(f1);
766 vec_sort(f2);
767 vec_add_to(f1, f2);
768 f = f1;
769}
770
771template <typename CoeffRing>
773 size_t start_row,
774 M2_arrayint perm) const
775{
776 size_t *perminv = newarray_atomic(size_t, perm->len);
777 for (size_t i = 0; i < perm->len; i++) perminv[perm->array[i]] = i;
778
779 size_t end_row = start_row + perm->len;
780
781 for (sparsevec *w = v; w != 0; w = w->next)
782 if (w->row >= start_row && w->row < end_row)
783 w->row = start_row + perminv[w->row - start_row];
784 vec_sort(v);
785 freemem(perminv);
786}
787
788template <typename CoeffRing>
790 size_t i,
791 size_t n_to_add) const
792{
793 for (sparsevec *w = v; w != 0 && w->row >= i; w = w->next) w->row += n_to_add;
794}
795
796template <typename CoeffRing>
797void SMat<CoeffRing>::vec_delete_rows(sparsevec *&v, size_t i, size_t j) const
798{
799 size_t n_to_delete = j - i + 1;
800 sparsevec head;
801 sparsevec *w = &head;
802 w->next = v;
803 while (w->next != 0 && w->next->row >= i)
804 if (w->next->row <= j)
805 {
806 // this row is up for the chopping block
807 sparsevec *tmp = w->next;
808 w->next = tmp->next;
809 vec_remove_node(tmp);
810 }
811 else
812 {
813 w = w->next;
814 w->row -= n_to_delete;
815 }
816 v = head.next;
817}
818
820// SMat //////////////////
822template <typename CoeffRing>
823SMat<CoeffRing>::SMat(const CoeffRing &coeffR0, size_t nrows, size_t ncols)
824 : coeffR(&coeffR0), nrows_(nrows), ncols_(ncols)
825{
826 initialize(nrows, ncols, 0);
827}
828
829template <typename CoeffRing>
835
836template <typename CoeffRing>
837void SMat<CoeffRing>::initialize(size_t nrows, size_t ncols, sparsevec **cols)
838{
839 nrows_ = nrows;
840 ncols_ = ncols;
841 columns_ = newarray(sparsevec *, ncols);
842 if (cols == 0)
843 {
844 for (size_t i = 0; i < ncols; i++) columns_[i] = 0;
845 }
846 else
847 {
848 for (size_t i = 0; i < ncols; i++) columns_[i] = vec_copy(*cols++);
849 }
850}
851
852template <typename CoeffRing>
860
861template <typename CoeffRing>
863{
864 return new SMat(*this);
865}
866
867template <typename CoeffRing>
868size_t SMat<CoeffRing>::lead_row(size_t col) const
869/* returns the largest index row which has a non-zero value in column 'col'.
870 returns -1 if the column is 0 */
871{
872 sparsevec *v = columns_[col];
873 if (v == 0) return -1;
874 return v->row;
875}
876
877template <typename CoeffRing>
878size_t SMat<CoeffRing>::lead_row(size_t col, elem &result) const
879/* returns the largest index row which has a non-zero value in column 'col'.
880 Also sets result to be the entry at this index.
881 returns -1 if the column is 0, or if col is out of range
882 No error is flagged. */
883{
884 sparsevec *v = columns_[col];
885 if (v == 0) return -1;
886 ring().init_set(result, v->coeff);
887 return v->row;
888}
889
891// Row and column operations //
893
894template <typename CoeffRing>
895bool SMat<CoeffRing>::get_entry(size_t r, size_t c, elem &result) const
896// Returns false if (r,c) is out of range or if result is 0. No error
897// is returned. result <-- this(r,c), and does not change result if false is returned.
898{
899 return vec_get_entry(columns_[c], r, result);
900}
901
902template <typename CoeffRing>
903void SMat<CoeffRing>::set_entry(size_t r, size_t c, const elem a)
904{
905 vec_set_entry(columns_[c], r, a);
906}
907
908template <typename CoeffRing>
909void SMat<CoeffRing>::interchange_rows(size_t i, size_t j)
910/* swap rows: row(i) <--> row(j) */
911{
912 for (size_t c = 0; c < ncols_; c++) vec_interchange_rows(columns_[c], i, j);
913}
914
915template <typename CoeffRing>
917/* swap columns: column(i) <--> column(j) */
918{
919 sparsevec *tmp = columns_[i];
920 columns_[i] = columns_[j];
921 columns_[j] = tmp;
922}
923
924template <typename CoeffRing>
926/* row(i) <- r * row(i) */
927{
928 for (size_t c = 0; c < ncols_; c++) vec_scale_row(columns_[c], i, r);
929}
930
931template <typename CoeffRing>
933/* column(i) <- r * column(i) */ { vec_scale(columns_[i], r); }
934template <typename CoeffRing>
936/* row(i) <- row(i) / r */
937{
938 for (size_t c = 0; c < ncols_; c++) vec_divide_row(columns_[c], i, r);
939}
940
941template <typename CoeffRing>
943/* column(i) <- column(i) / r */ { vec_divide(columns_[i], r); }
944template <typename CoeffRing>
945void SMat<CoeffRing>::row_op(size_t i, elem r, size_t j)
946/* row(i) <- row(i) + r * row(j) */
947{
948 for (size_t c = 0; c < ncols_; c++) vec_row_op(columns_[c], i, r, j);
949}
950
951template <typename CoeffRing>
952void SMat<CoeffRing>::column_op(size_t i, elem r, size_t j)
953/* column(i) <- column(i) + r * column(j) */
954{
956}
957
958template <typename CoeffRing>
960 size_t r2,
961 elem a1,
962 elem a2,
963 elem b1,
964 elem b2)
965/* row(r1) <- a1 * row(r1) + a2 * row(r2),
966 row(r2) <- b1 * row(r1) + b2 * row(r2)
967*/
968{
969 for (size_t c = 0; c < ncols_; c++)
970 vec_row_op2(columns_[c], r1, r2, a1, a2, b1, b2);
971}
972
973template <typename CoeffRing>
975 size_t c2,
976 elem a1,
977 elem a2,
978 elem b1,
979 elem b2)
980/* column(c1) <- a1 * column(c1) + a2 * column(c2),
981 column(c2) <- b1 * column(c1) + b2 * column(c2)
982*/
983{
984 // Make first column: v1 = a1*c1+a2*c2
985 sparsevec *v1 = vec_copy(columns_[c1]);
986 sparsevec *v2 = vec_copy(columns_[c2]);
987 vec_scale(v1, a1);
988 vec_scale(v2, a2);
989 vec_add_to(v1, v2);
990
991 // Second column: w1 = b1*c1 + b2*c2
992 sparsevec *w1 = columns_[c1];
993 sparsevec *w2 = columns_[c2];
994 vec_scale(w1, b1);
995 vec_scale(w2, b2);
996 vec_add_to(w1, w2);
997
998 // Set the matrices:
999 columns_[c1] = v1;
1000 columns_[c2] = w1;
1001}
1002
1003template <typename CoeffRing>
1004void SMat<CoeffRing>::dot_product(size_t i, size_t j, elem &result) const
1005{
1007}
1008
1009template <typename CoeffRing>
1010bool SMat<CoeffRing>::row_permute(size_t start_row, M2_arrayint perm)
1011{
1012 // We copy one row to another location for each cycle in 'perm' of length > 1.
1013 size_t nrows_to_permute = perm->len;
1014 bool *done = newarray_atomic(bool, nrows_to_permute);
1015 for (size_t i = 0; i < nrows_to_permute; i++) done[i] = true;
1016 for (size_t i = 0; i < nrows_to_permute; i++)
1017 {
1018 size_t j = perm->array[i];
1019 if (!done[j])
1020 {
1021 ERROR("expected permutation");
1022 freemem(done);
1023 return false;
1024 }
1025 done[j] = false;
1026 }
1027 for (size_t c = 0; c < ncols_; c++) vec_permute(columns_[c], start_row, perm);
1028 return true;
1029}
1030
1031template <typename CoeffRing>
1033{
1034 size_t ncols_to_permute = perm->len;
1035 bool *done = newarray_atomic(bool, ncols_to_permute);
1036 sparsevec **tmpvecs = newarray(sparsevec *, ncols_to_permute);
1037 for (size_t i = 0; i < ncols_to_permute; i++) done[i] = true;
1038 for (size_t i = 0; i < ncols_to_permute; i++)
1039 {
1040 size_t j = perm->array[i];
1041 if (!done[j])
1042 {
1043 ERROR("expected permutation");
1044 freemem(done);
1045 return false;
1046 }
1047 done[j] = false;
1048 }
1049 for (size_t i = 0; i < ncols_to_permute; i++)
1050 tmpvecs[i] = columns_[start_col + perm->array[i]];
1051 for (size_t i = 0; i < ncols_to_permute; i++)
1052 columns_[start_col + i] = tmpvecs[i];
1053 freemem(tmpvecs);
1054 freemem(done);
1055 return true;
1056}
1057
1058template <typename CoeffRing>
1059void SMat<CoeffRing>::insert_columns(size_t i, size_t n_to_add)
1060/* Insert n_to_add columns directly BEFORE column i. */
1061{
1062 sparsevec **tmp = columns_;
1063 columns_ = 0;
1064 size_t orig_ncols = ncols_;
1065
1066 initialize(nrows_, ncols_ + n_to_add, 0);
1067 for (size_t c = 0; c < i; c++) columns_[c] = tmp[c];
1068 for (size_t c = i; c < orig_ncols; c++) columns_[c + n_to_add] = tmp[c];
1069
1070 freemem(tmp);
1071}
1072
1073template <typename CoeffRing>
1074void SMat<CoeffRing>::insert_rows(size_t i, size_t n_to_add)
1075/* Insert n_to_add rows directly BEFORE row i. */
1076{
1077 for (size_t c = 0; c < ncols_; c++) vec_insert_rows(columns_[c], i, n_to_add);
1078 nrows_ += n_to_add;
1079}
1080
1081template <typename CoeffRing>
1082void SMat<CoeffRing>::delete_columns(size_t i, size_t j)
1083/* Delete columns i .. j from M */
1084{
1085 for (size_t c = i; c <= j; c++) vec_remove(columns_[c]);
1086 sparsevec **tmp = columns_;
1087 columns_ = 0;
1088 size_t ndeleted = j - i + 1;
1089 size_t orig_ncols = ncols_;
1090
1091 initialize(nrows_, ncols_ - (j - i + 1), 0);
1092 for (size_t c = 0; c < i; c++) columns_[c] = tmp[c];
1093 for (size_t c = j + 1; c < orig_ncols; c++) columns_[c - ndeleted] = tmp[c];
1094
1095 freemem(tmp);
1096}
1097
1098template <typename CoeffRing>
1099void SMat<CoeffRing>::delete_rows(size_t i, size_t j)
1100/* Delete rows i .. j from M */
1101{
1102 for (size_t c = 0; c < ncols_; c++) vec_delete_rows(columns_[c], i, j);
1103 nrows_ -= (j - i + 1);
1104}
1105
1106template <typename CoeffRing>
1108{
1109 for (size_t c = 0; c < ncols_; c++)
1110 if (columns_[c] != 0) return false;
1111 return true;
1112}
1113
1114template <typename CoeffRing>
1116{
1117 assert(&ring() == &B.ring());
1118 if (B.numRows() != numRows()) return false;
1119 if (B.numColumns() != numColumns()) return false;
1120 for (size_t c = 0; c < numColumns(); c++)
1121 {
1122 sparsevec *v = columns_[c];
1123 sparsevec *w = B.columns_[c];
1124 if (!vec_equals(v, w)) return false;
1125 }
1126 return true;
1127}
1128
1129template <typename CoeffRing>
1131 M2_arrayint rows,
1132 M2_arrayint cols)
1133{
1134 coeffR = A.coeffR;
1135 initialize(rows->len, cols->len, NULL);
1136 typename CoeffRing::Element f(*coeffR);
1137 for (size_t r = 0; r < rows->len; r++)
1138 for (size_t c = 0; c < cols->len; c++)
1139 {
1140 coeffR->set_zero(f);
1141 A.get_entry(rows->array[r], cols->array[c], f);
1142 set_entry(r, c, f);
1143 }
1144}
1145
1146template <typename CoeffRing>
1148{
1149 coeffR = A.coeffR;
1150 initialize(A.numRows(), cols->len, NULL);
1151 typename CoeffRing::Element f(*coeffR);
1152 for (size_t r = 0; r < nrows_; r++)
1153 for (size_t c = 0; c < cols->len; c++)
1154 {
1155 coeffR->set_zero(f);
1156 A.get_entry(r, cols->array[c], f);
1157 set_entry(r, c, f);
1158 }
1159}
1160
1161template <typename CoeffRing>
1163// return this + B. return NULL of sizes or types do not match.
1164{
1165 assert(&B.ring() == &ring());
1166 assert(B.numRows() == numRows());
1167 assert(B.numColumns() == numColumns());
1168
1169 for (size_t c = 0; c < numColumns(); c++)
1170 {
1171 sparsevec *v = vec_copy(B.columns_[c]);
1172 vec_add_to(columns_[c], v);
1173 }
1174}
1175
1176template <typename CoeffRing>
1178// this -= B.
1179// assumption:the assert statements below:
1180{
1181 assert(&B.ring() == &ring());
1182 assert(B.numRows() == numRows());
1183 assert(B.numColumns() == numColumns());
1184
1185 for (size_t c = 0; c < numColumns(); c++)
1186 {
1187 sparsevec *v = vec_copy(B.columns_[c]);
1188 vec_negate(v);
1189 vec_add_to(columns_[c], v);
1190 }
1191}
1192
1193template <typename CoeffRing>
1195// this = -this
1196{
1197 for (size_t c = 0; c < numColumns(); c++)
1198 for (sparsevec *p = columns_[c]; p != NULL; p = p->next)
1199 ring().negate(p->coeff, p->coeff);
1200}
1201
1202template <typename CoeffRing>
1204// this = f * this
1205{
1206 for (size_t c = 0; c < numColumns(); c++) vec_scale(columns_[c], f);
1207}
1208
1209#endif
1210
1211// Local Variables:
1212// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1213// indent-tabs-mode: nil
1214// End:
Legacy Z_mod — a Ring-derived Z/p with log / exp tables.
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Definition mat.hpp:79
xxx xxx xxx
Definition ring.hpp:102
bool valid()
Definition smat.hpp:123
iterator(const SMat< CoeffRing > *M0)
Definition smat.hpp:120
size_t col
Definition smat.hpp:111
void copy_elem(ring_elem &result)
Definition smat.hpp:125
const SMat< CoeffRing > * M
Definition smat.hpp:110
size_t row()
Definition smat.hpp:124
const elem & value()
Definition smat.hpp:121
sparsevec * v
Definition smat.hpp:112
void next()
Definition smat.hpp:122
void set(size_t col0)
Definition smat.hpp:115
iterator begin() const
Definition smat.hpp:131
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 vec_insert_rows(sparsevec *&v, size_t i, size_t n_to_add) const
Definition smat.hpp:789
void insert_columns(size_t i, size_t n_to_add)
Definition smat.hpp:1059
const CoeffRing & ring() const
Definition smat.hpp:104
CoeffRing::Element Element
Definition smat.hpp:52
void delete_columns(size_t i, size_t j)
Definition smat.hpp:1082
virtual ~SMat()
Definition smat.hpp:88
void vec_remove(sparsevec *&v) const
Definition smat.hpp:294
sparsevec * vec_new() const
Definition smat.hpp:281
bool is_zero() const
Definition smat.hpp:1107
bool row_permute(size_t start_row, M2_arrayint perm)
Definition smat.hpp:1010
void vec_set_entry(sparsevec *&v, size_t r, const elem &result) const
Definition smat.hpp:347
void vec_scale_row(sparsevec *&v, size_t r, const elem &a) const
Definition smat.hpp:437
void vec_permute(sparsevec *&v, size_t start_row, M2_arrayint perm) const
Definition smat.hpp:772
void vec_sort(sparsevec *&v) const
Definition smat.hpp:746
RT CoeffRing
Definition smat.hpp:48
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
void vec_column_op(sparsevec *&v, const elem &a, sparsevec *w) const
Definition smat.hpp:710
SMat< CoeffRing > * copy() const
Definition smat.hpp:862
void vec_row_op2(sparsevec *&v, size_t r1, size_t r2, const elem &a1, const elem &a2, const elem &b1, const elem &b2) const
Definition smat.hpp:664
size_t lead_row(size_t col) const
Definition smat.hpp:868
ElementType elem
Definition smat.hpp:51
void vec_divide_row(sparsevec *&v, size_t r, const elem &a) const
Definition smat.hpp:493
bool is_dense() const
Definition smat.hpp:98
void vec_divide(sparsevec *&v, const elem &a) const
Definition smat.hpp:517
void column2by2(size_t c1, size_t c2, elem a1, elem a2, elem b1, elem b2)
Definition smat.hpp:974
void vec_scale(sparsevec *&v, const elem &a) const
Definition smat.hpp:461
void addInPlace(const SMat &B)
Definition smat.hpp:1162
void scalarMultInPlace(const elem &f)
Definition smat.hpp:1203
void vec_row_op(sparsevec *&v, size_t r1, const elem &a, size_t r2) const
Definition smat.hpp:614
void delete_rows(size_t i, size_t j)
Definition smat.hpp:1099
void vec_remove_node(sparsevec *&v) const
Definition smat.hpp:287
void negateInPlace()
Definition smat.hpp:1194
void scale_column(size_t i, elem r)
Definition smat.hpp:932
void vec_dot_product(sparsevec *v, sparsevec *w, elem &result) const
Definition smat.hpp:721
void vec_delete_rows(sparsevec *&v, size_t i, size_t j) const
Definition smat.hpp:797
size_t nrows_
Definition smat.hpp:232
bool is_equal(const SMat &B) const
Definition smat.hpp:1115
void row_op(size_t i, elem r, size_t j)
Definition smat.hpp:945
const Ring * R
Definition smat.hpp:229
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
void vec_negate(sparsevec *&v) const
Definition smat.hpp:486
SMat(const SMat< ACoeffRing > &M, size_t nrows, size_t ncols)
bool get_entry(size_t r, size_t c, elem &result) const
Definition smat.hpp:895
sparsevec * column(size_t c)
Definition smat.hpp:69
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
void vec_interchange_rows(sparsevec *&v, size_t r1, size_t r2) const
Definition smat.hpp:383
void grab(SMat *M)
Definition smat.hpp:853
size_t lead_row(size_t col, elem &result) const
Definition smat.hpp:878
void setFromSubmatrix(const SMat &A, M2_arrayint cols)
Definition smat.hpp:1147
size_t numRows() const
Definition smat.hpp:99
bool column_permute(size_t start_col, M2_arrayint perm)
Definition smat.hpp:1032
void vec_add_to(sparsevec *&v, sparsevec *&w) const
Definition smat.hpp:542
SMat(const SMat< ACoeffRing > &M)
Definition smat.hpp:830
void subtractInPlace(const SMat &B)
Definition smat.hpp:1177
const sparsevec * column(size_t c) const
Definition smat.hpp:64
size_t numColumns() const
Definition smat.hpp:100
CoeffRing::elem ElementType
Definition smat.hpp:49
bool vec_get_entry(const sparsevec *v, size_t r, elem &result) const
Definition smat.hpp:331
SMat(const CoeffRing &coeffR0, size_t nrows, size_t ncols)
Definition smat.hpp:823
void setFromSubmatrix(const SMat &A, M2_arrayint rows, M2_arrayint cols)
Definition smat.hpp:1130
sparsevec * vec_copy(const sparsevec *v) const
Definition smat.hpp:305
bool vec_equals(const sparsevec *v, const sparsevec *w) const
Definition smat.hpp:323
SMat()
Definition smat.hpp:76
void insert_rows(size_t i, size_t n_to_add)
Definition smat.hpp:1074
sparsevec ** columns_
Definition smat.hpp:234
void initialize(size_t nrows, size_t ncols, sparsevec **cols)
Definition smat.hpp:837
size_t ncols_
Definition smat.hpp:233
void dot_product(size_t i, size_t j, elem &result) const
Definition smat.hpp:1004
const CoeffRing * coeffR
Definition smat.hpp:231
int p
void freemem(void *s)
Definition m2-mem.cpp:103
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
#define newarray(T, len)
Definition newdelete.hpp:82
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
ElementType coeff
Definition smat.hpp:60
size_t row
Definition smat.hpp:59
sparsevec * next
Definition smat.hpp:58