You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
multirow/qxx/src/smat.cpp

340 lines
6.4 KiB

/*
This file is part of qxx -- matrix algebra in exact arithmetic
Copyright (C) 2013-2014 Laurent Poirrier
libp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pxx. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include "qxx/debug.hpp"
#include "qxx/rational.hpp"
#include "qxx/dvec.hpp"
#include "qxx/slu.hpp"
#include "qxx/smat.hpp"
// **************************************************************************
//
// **************************************************************************
namespace q {
// **************************************************************************
//
// **************************************************************************
smat::smat()
: m(0), n(0)
{
}
smat::smat(const smat &b)
: m(b.m), n(b.n), d(b.d)
{
}
smat::smat(int m0, int n0)
: m(m0), n(n0), d(m0)
{
for (int i = 0; i < m; i++)
d[i].resize(n);
}
int smat::rows() const
{
return(m);
}
int smat::cols() const
{
return(n);
}
void smat::resize(int m0, int n0)
{
m = m0;
n = n0;
d.resize(m);
for (int i = 0; i < m; i++)
d[i].resize(n);
}
void smat::clear()
{
m = n = 0;
d.clear();
}
// **************************************************************************
//
// **************************************************************************
const mpq &smat::get(int i, int j) const
{
Q_RANGE_CHECK(i, 0, m - 1);
Q_RANGE_CHECK(j, 0, n - 1);
return(d[i][j]);
}
void smat::set(int i, int j, const mpq &v)
{
Q_RANGE_CHECK(i, 0, m - 1);
Q_RANGE_CHECK(j, 0, n - 1);
d[i][j] = v;
}
void smat::set_zero()
{
for (int i = 0; i < m; i++)
d[i].set_zero();
}
void smat::set_identity()
{
mpq one(1);
for (int i = 0; i < m; i++) {
d[i].set_zero();
d[i][i] = one;
}
}
// **************************************************************************
//
// **************************************************************************
void smat::gather(const dmat &src)
{
resize(src.rows(), src.cols());
for (int i = 0; i < m; i++)
d[i].gather(src[i]);
}
void smat::spread(dmat &r) const
{
r.resize(m, n);
for (int i = 0; i < m; i++)
d[i].spread(r[i]);
}
dmat smat::dense() const
{
dmat r;
spread(r);
return(r);
}
// **************************************************************************
//
// **************************************************************************
svec smat::get_col(int j) const
{
svec r(m);
for (int i = 0; i < m; i++)
r.push(i, d[i][j]);
return(r);
}
void smat::set_col(int j, const svec &v)
{
Q_MATCH(v.size(), m);
for (int i = 0; i < m; i++)
d[i][j] = v[i];
}
const svec &smat::get_row(int i) const
{
return(d[i]);
}
void smat::set_row(int i, const svec &v)
{
Q_MATCH(v.size(), n);
d[i] = v;
}
// **************************************************************************
//
// **************************************************************************
svec &smat::operator[] (int i)
{
return(d[i]);
}
const svec &smat::operator[] (int i) const
{
return(d[i]);
}
// **************************************************************************
//
// **************************************************************************
svec_ref smat::operator() (int i, int j)
{
Q_RANGE_CHECK(i, 0, m - 1);
Q_RANGE_CHECK(j, 0, n - 1);
return(d[i][j]);
}
const mpq &smat::operator() (int i, int j) const
{
Q_RANGE_CHECK(i, 0, m - 1);
Q_RANGE_CHECK(j, 0, n - 1);
return(d[i][j]);
}
// **************************************************************************
//
// **************************************************************************
smat &smat::operator=(const smat &a)
{
m = a.m;
n = a.n;
d = a.d;
return(*this);
}
// **************************************************************************
//
// **************************************************************************
dvec smat::operator*(const dvec &b) const
{
Q_MATCH(n, b.size());
dvec x(m);
mpq v;
for (int i = 0; i < m; i++) {
v = 0;
const svec &r = d[i];
for (int l = 0; l < r.nz(); l++)
v += r.value(l) * b[r.index(l)];
x[i] = v;
}
return(x);
}
// **************************************************************************
//
// **************************************************************************
void smat::set_transpose(const smat &a)
{
resize(a.n, a.m);
for (int i = 0; i < a.n; i++) {
const svec &ar = a[i];
for (int l = 0; l < ar.nz(); l++)
d[ar.index(l)].push(i, ar.value(l));
}
}
// **************************************************************************
//
// **************************************************************************
smat smat::t() const
{
smat a;
a.set_transpose(*this);
return(a);
}
// **************************************************************************
//
// **************************************************************************
smat smat::inv() const
{
Q_MATCH(m, n);
slu lu(*this);
smat g;
dvec e;
svec x;
g.resize(n, n);
e.assign(n, 0);
for (int i = 0; i < n; i++) {
e[i] = 1;
x = lu.solve_xA(e);
g.set_row(i, x);
e[i] = 0;
}
return(g);
}
// **************************************************************************
//
// **************************************************************************
void smat::fdump(FILE *f, const std::string &name) const
{
if (name.length())
gmp_fprintf(f, "%s = [\n", name.c_str());
else
gmp_fprintf(f, "[\n");
for (int i = 0; i < m; i++)
d[i].fdump(f);
gmp_fprintf(f, "];\n");
}
void smat::dump(const std::string &name) const
{
fdump(stdout, name);
}
// **************************************************************************
//
// **************************************************************************
std::ostream &operator<<(std::ostream &os, const smat &a)
{
for (int i = 0; i < a.rows(); i++)
os << a[i] << std::endl;
return(os);
}
// **************************************************************************
//
// **************************************************************************
}