void SMat<CoeffRing>::vec_set_entry(sparsevec *&v, size_t r, const elem &a) const { sparsevec *p; bool iszero = ring().is_zero(a); sparsevec head; head.next = v; for (p = &head; p->next != 0; p = p->next) if (p->next->row <= r) break; if (p->next == 0 || p->next->row < r) { if (iszero) return; sparsevec *w = vec_new(); w->next = p->next; w->row = r; ring().init_set(w->coeff, a); p->next = w; } else if (p->next->row == r) { if (iszero) { // delete node sparsevec *tmp = p->next; p->next = tmp->next; vec_remove_node(tmp); } else ring().set(p->next->coeff, a); } v = head.next; }
void SMat<CoeffRing>::vec_remove(sparsevec *&v) const { while (v != 0) { sparsevec *tmp = v; v = v->next; vec_remove_node(tmp); } }
void SMat<CoeffRing>::vec_row_op(sparsevec *&v, size_t r1, const elem &a, size_t r2) const // row(r1 in v) := row(r1 in v) + a * row(r2 in v) { sparsevec *p; sparsevec *vec2 = 0; for (p = v; p != 0; p = p->next) if (p->row == r2) { vec2 = p; break; } if (vec2 == 0) return; elem c; ring().init(c); ring().set_zero(c); ring().mult(c, vec2->coeff, a); if (ring().is_zero(c)) return; // nothing to change // Now add c to the r1'th row of v sparsevec head; head.next = v; for (p = &head; p->next != 0; p = p->next) if (p->next->row <= r1) break; if (p->next == 0 || p->next->row < r1) { // Make a new node sparsevec *w = vec_new(); w->next = p->next; w->row = r1; ring().init_set(w->coeff, c); p->next = w; } else { ring().add(p->next->coeff, p->next->coeff, c); if (ring().is_zero(p->next->coeff)) { sparsevec *tmp = p->next; p->next = tmp->next; vec_remove_node(tmp); } } v = head.next; ring().clear(c); }
void SMat<CoeffRing>::vec_divide_row(sparsevec *&v, size_t r, const elem &a) const { sparsevec head; head.next = v; for (sparsevec *p = &head; p->next != 0; p = p->next) if (p->next->row < r) break; else if (p->next->row == r) { ring().divide(p->next->coeff, p->next->coeff, a); if (ring().is_zero(p->next->coeff)) { sparsevec *tmp = p->next; p->next = tmp->next; vec_remove_node(tmp); } break; } v = head.next; }
void SMat<CoeffRing>::vec_delete_rows(sparsevec *&v, size_t i, size_t j) const { size_t n_to_delete = j - i + 1; sparsevec head; sparsevec *w = &head; w->next = v; while (w->next != 0 && w->next->row >= i) if (w->next->row <= j) { // this row is up for the chopping block sparsevec *tmp = w->next; w->next = tmp->next; vec_remove_node(tmp); } else { w = w->next; w->row -= n_to_delete; } v = head.next; }
void SMat<CoeffRing>::vec_divide(sparsevec *&v, const elem &a) const { if (ring().is_zero(a)) { vec_remove(v); v = 0; return; } sparsevec head; head.next = v; for (sparsevec *p = &head; p->next != 0; p = p->next) { ring().divide(p->next->coeff, p->next->coeff, a); if (ring().is_zero(p->next->coeff)) { sparsevec *tmp = p->next; p->next = tmp->next; vec_remove_node(tmp); if (p->next == 0) break; } } v = head.next; }
void SMat<CoeffRing>::vec_add_to(sparsevec *&v, sparsevec *&w) const // v := v+w, w := 0 { if (w == 0) return; if (v == 0) { v = w; w = 0; return; } sparsevec head; sparsevec *result = &head; while (true) if (v->row < w->row) { result->next = w; result = result->next; w = w->next; if (w == 0) { result->next = v; v = head.next; return; } } else if (v->row > w->row) { result->next = v; result = result->next; v = v->next; if (v == 0) { result->next = w; v = head.next; w = 0; return; } } else { sparsevec *tmv = v; sparsevec *tmw = w; v = v->next; w = w->next; ring().add(tmv->coeff, tmv->coeff, tmw->coeff); if (ring().is_zero(tmv->coeff)) { vec_remove_node(tmv); } else { result->next = tmv; result = result->next; } vec_remove_node(tmw); if (w == 0) { result->next = v; v = head.next; return; } if (v == 0) { result->next = w; v = head.next; w = 0; return; } } }