Macaulay2 Engine
Loading...
Searching...
No Matches
mutablemat-imp.hpp
Go to the documentation of this file.
1// Copyright 2015 Anton Leykin and Mike Stillman
2
3// Anton Leykin's code in this file is in the public domain.
4
5#ifndef _mutable_mat_imp_hpp_
6#define _mutable_mat_imp_hpp_
7
39
40template <typename Mat>
42 M2_arrayint constsPos,
43 M2_arrayint varsPos) const
44{
45 if (n_rows() != 1 || n_cols() != constsPos->len) {
46 ERROR("1-row matrix expected; or numbers of constants don't match");
47 return nullptr;
48 } else return new M2SLEvaluator(
49 new SLEvaluatorConcrete<typename Mat::CoeffRing> (&(P->value()), constsPos, varsPos, this)
50 );
51}
52
53template <typename Mat>
55 M2_string libName,
56 int nInputs,
57 int nOutputs) const
58{
59 return new M2SLEvaluator(
60 new SLEvaluatorConcrete<typename Mat::CoeffRing> (libName, nInputs, nOutputs, this)
61 );
62}
63
64template <typename T>
65size_t MutableMat<T>::rank() const
66{
67 return MatrixOps::rank(mat);
68}
69
70template <typename T>
72{
73 ring_elem det;
74 typename T::ElementType a;
75 mat.ring().init(a);
77 // MatrixOps::BasicLinAlg<MatType>::determinant(mat, a);
78 mat.ring().to_ring_elem(det, a);
79 mat.ring().clear(a);
80 return RingElement::make_raw(get_ring(), det);
81}
82
83template <typename T>
85{
86 assert(n_rows() == n_cols());
88 bool val = MatrixOps::inverse(mat, result->mat);
89 if (!val)
90 {
91 delete result;
92 return 0;
93 }
94 return result;
95}
96
97template <typename T>
99{
101 try
102 {
103 // ignore returned value (the rank of mat):
105 return result;
106 } catch (const exc::engine_error& e)
107 {
108 delete result;
109 throw;
110 }
111}
112
113template <typename T>
115{
116 const T* B1 = B->coerce_const<T>();
117 if (B1 == 0) throw exc::engine_error("expected matrices of the same type");
118 if (B->get_ring() != get_ring())
119 throw exc::engine_error("expected same ring");
120 if (B->n_rows() != n_rows())
121 throw exc::engine_error("expected matrices with same number of rows");
122 MutableMat<T>* solns = makeZeroMatrix(0, 0);
123 bool retval = MatrixOps::solveLinear(mat, *B1, solns->mat);
124 if (retval) return solns;
125 delete solns;
126 return NULL;
127}
128
129template <typename T>
131{
132 const T* B1 = B->coerce_const<T>();
133 if (B1 == 0) throw exc::engine_error("expected matrices of the same type");
134 if (B->get_ring() != get_ring())
135 throw exc::engine_error("expected same ring");
136 if (n_rows() != n_cols()) throw exc::engine_error("expected a square matrix");
137 if (B->n_rows() != n_rows())
138 throw exc::engine_error("expected matrices with same number of rows");
139 MutableMat<T>* solns = makeZeroMatrix(0, 0);
140 bool retval = MatrixOps::solveInvertible(mat, *B1, solns->mat);
141 if (retval) return solns;
142 delete solns;
143 return NULL;
144}
145
146template <typename T>
148{
149 MutableMat<T>* ker = makeZeroMatrix(0, 0);
150 MatrixOps::nullSpace(mat, ker->mat); // ignore return value of nullSpace...
151 return ker;
152}
153
154template <typename T>
155MutableMatrix /* or null */* MutableMat<T>::mult(const MutableMatrix* B) const
156{
157 // First, make sure B has the same ring/type as 'this'.
158 const T* B1 = B->coerce_const<T>();
159 if (B1 == 0)
160 {
161 ERROR(
162 "mutable matrix/ring type for (mutable) matrix multiplication "
163 "required to be the same");
164 return 0;
165 }
166 // Second, make sure the sizes are correct.
167 if (mat.numColumns() != B1->numRows())
168 {
169 ERROR("matrix sizes do not match in matrix multiplication");
170 return 0;
171 }
172 // create the result matrix
173 MutableMat<T>* result = makeZeroMatrix(n_rows(), B1->numColumns());
174 MatrixOps::mult(mat, *B1, result->mat);
175
176 return result;
177}
178
179template <typename T>
181 const MutableMatrix* B)
182{
183 // First: make sure that A, B have the right ring/matrix type
184 const T* A1 = A->coerce_const<T>();
185 const T* B1 = B->coerce_const<T>();
186 if (A1 == 0 or B1 == 0)
187 throw exc::engine_error(
188 "mutable matrix/ring type for (mutable) matrix multiplication required "
189 "to be the same");
190 if (mat.numRows() != A1->numRows() or mat.numColumns() != B1->numColumns())
191 throw exc::engine_error(
192 "expected matrix sizes to be compatible with matrix multiplication");
193 MatrixOps::addMultipleTo(mat, *A1, *B1);
194}
195
196template <typename T>
198 const MutableMatrix* B)
199{
200 // First: make sure that A, B have the right ring/matrix type
201 const T* A1 = A->coerce_const<T>();
202 const T* B1 = B->coerce_const<T>();
203 if (A1 == 0 or B1 == 0)
204 throw exc::engine_error(
205 "mutable matrix/ring type for (mutable) matrix multiplication required "
206 "to be the same");
207 if (mat.numRows() != A1->numRows() or mat.numColumns() != B1->numColumns())
208 throw exc::engine_error(
209 "expected matrix sizes to be compatible with matrix multiplication");
211}
212
213template <typename T>
215{
216 // LUComputation<T> C(mat);
217 // return C.rankProfile(row_profile);
218 return MatrixOps::rankProfile(mat, row_profile);
219}
220
221template <typename T>
223{
224 // std::cout << "MutableMat<T>::LU\n";
225 T* L1 = L->coerce<T>();
226 T* U1 = U->coerce<T>();
227 if (L1 == 0 or U1 == 0)
228 throw exc::engine_error("expected matrices of the same ring/type");
229 return MatrixOps::LU(mat, *L1, *U1);
230}
231
232template <typename T> // T should be a matrix type, generally DMat<RT>
234 const MutableMatrix* v,
235 int m)
236{
237 T* LU1 = this->coerce<T>();
238 const T* v1 = const_cast<MutableMatrix*>(v)->coerce<T>();
239 if (LU1 == nullptr or v1 == nullptr)
240 throw exc::engine_error("expected matrices of the same ring/type");
241 return MatrixOps::LUincremental(P, *LU1, *v1, m);
242}
243
244template <typename T> // T should be a matrix type, generally DMat<RT>
246 int m,
247 int strategy)
248{
249 T* Lv1 = this->coerce<T>();
250 T* x1 = x->coerce<T>();
251 if (Lv1 == nullptr or x1 == nullptr)
252 throw exc::engine_error("expected matrices of the same ring/type");
253 MatrixOps::triangularSolve(*Lv1, *x1, m, strategy);
254}
255
256template <typename T>
258 bool is_symm_or_hermitian) const
259{
260 if (!is_dense())
261 throw exc::engine_error(
262 "'eigenvalues' is only implemented for dense matrices");
263 if (is_symm_or_hermitian)
264 {
265 auto E1 = eigenvals->coerce<DMat<HermitianEigenvalueType> >();
266 if (E1 == 0)
267 throw exc::engine_error("eigenvalue matrix is of the wrong type/ring");
269 }
270 else
271 {
272 auto E1 = eigenvals->coerce<DMat<EigenvalueType> >();
273 if (E1 == 0)
274 throw exc::engine_error("eigenvalue matrix is of the wrong type/ring");
275 return MatrixOps::eigenvalues(mat, *E1);
276 }
277}
278
279template <typename T>
281 MutableMatrix* eigenvecs,
282 bool is_symm_or_hermitian) const
283{
284 if (!is_dense())
285 throw exc::engine_error(
286 "'eigenvalues' is only implemented for dense matrices");
287 if (is_symm_or_hermitian)
288 {
293 if (E1 == 0 or evecs1 == 0)
294 throw exc::engine_error(
295 "eigenvalue/vector matrix is of the wrong type/ring");
296 return MatrixOps::eigenvectorsHermitian(mat, *E1, *evecs1);
297 }
298 else
299 {
301 DMat<EigenvectorType>* evecs1 =
302 eigenvecs->coerce<DMat<EigenvectorType> >();
303 if (E1 == 0 or evecs1 == 0)
304 throw exc::engine_error(
305 "eigenvalue/vector matrix is of the wrong type/ring");
306 return MatrixOps::eigenvectors(mat, *E1, *evecs1);
307 }
308}
309
310template <typename T>
312 MutableMatrix* X,
313 bool assume_full_rank) const
314{
315 const T* B1 = B->coerce_const<T>();
316 T* X1 = X->coerce<T>();
317 if (B1 == 0 or X1 == 0)
318 throw exc::engine_error("expected matrices of the same type");
319 bool retval = MatrixOps::leastSquares(mat, *B1, *X1, assume_full_rank);
320 return retval;
321}
322
323template <typename T>
324bool MutableMat<T>::QR(MutableMatrix* Q, MutableMatrix* R, bool return_QR) const
325{
326 if (!is_dense())
327 throw exc::engine_error("'QR' is only implemented for dense matrices");
328
329 auto Q1 = Q->coerce<DMat<CoeffRing> >();
330 if (Q1 == 0) throw exc::engine_error("Q matrix is of the wrong type/ring");
331 auto R1 = R->coerce<DMat<CoeffRing> >();
332 if (R1 == 0) throw exc::engine_error("R matrix is of the wrong type/ring");
333 return MatrixOps::QR(mat, *Q1, *R1, return_QR);
334}
335
336template <typename T>
338 MutableMatrix* U,
339 MutableMatrix* Vt,
340 bool use_divide_and_conquer) const
341{
342 auto Sigma2 = Sigma->coerce<DMat<HermitianEigenvalueType> >();
343 T* U2 = U->coerce<T>();
344 T* Vt2 = Vt->coerce<T>();
345 if (Sigma2 == 0 || U2 == 0 || Vt2 == 0)
346 throw exc::engine_error("expected matrices of the same type");
347 int strategy = (use_divide_and_conquer ? 1 : 0);
348 return MatrixOps::SVD(mat, *Sigma2, *U2, *Vt2, strategy);
349}
350
351template <typename Mat>
353 bool transpose)
354{
355 (void) transpose;
356 throw exc::engine_error(
357 "LU decomposition currently not implemented for this ring and matrix "
358 "type");
359}
360
361template <typename T>
363{
364 MatrixOps::clean(epsilon, mat);
365}
366
367template <typename T>
369{
370 if (get_ring()->get_precision() == 0)
371 throw exc::engine_error("expected a matrix over RR or CC");
372
374 mpfr_init2(nm, get_ring()->get_precision());
375 mpfr_set_si(nm, 0, MPFR_RNDN);
376
378 return moveTo_gmpRR(nm);
379}
380
381#endif
382
383// Local Variables:
384// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
385// indent-tabs-mode: nil
386// End:
Definition dmat.hpp:62
MutableEngineObject wrapper holding a raw SLEvaluator*.
Definition SLP-defs.hpp:248
SLProgram & value()
Definition SLP-defs.hpp:69
MutableEngineObject wrapper that owns an SLProgram via unique_ptr.
Definition SLP-defs.hpp:64
virtual M2SLEvaluator * createCompiledSLEvaluator(M2_string libName, int nInputs, int nOutputs) const
virtual bool eigenvalues(MutableMatrix *eigenvals, bool is_symm_or_hermitian) const
virtual size_t rank() const
Fast linear algebra routines (well, fast for some rings).
virtual const RingElement * determinant() const
virtual engine_RawArrayIntPairOrNull LQUPFactorizationInPlace(bool transpose)
LU decomposition routines /////.
virtual bool QR(MutableMatrix *Q, MutableMatrix *R, bool return_QR) const
virtual M2_arrayintOrNull rankProfile(bool row_profile) const
virtual MutableMatrix * solveLinear(const MutableMatrix *B) const
virtual size_t n_rows() const
virtual M2_arrayintOrNull LUincremental(std::vector< size_t > &P, const MutableMatrix *v, int i)
virtual M2SLEvaluator * createSLEvaluator(M2SLProgram *P, M2_arrayint constsPos, M2_arrayint varsPos) const
virtual gmp_RRorNull norm() const
virtual void subtractMultipleTo(const MutableMatrix *A, const MutableMatrix *B)
virtual MutableMatrix * nullSpace() const
virtual size_t n_cols() const
virtual MutableMatrix * solveInvertible(const MutableMatrix *B) const
virtual bool least_squares(const MutableMatrix *b, MutableMatrix *x, bool assume_full_rank) const
virtual void addMultipleTo(const MutableMatrix *A, const MutableMatrix *B)
virtual void clean(gmp_RR epsilon)
virtual MutableMat * transpose() const
virtual MutableMat * mult(const RingElement *f) const
virtual bool SVD(MutableMatrix *Sigma, MutableMatrix *U, MutableMatrix *Vt, bool use_divide_and_conquer) const
virtual void triangularSolve(MutableMatrix *x, int m, int strategy)
virtual const Ring * get_ring() const
MutableMat * makeZeroMatrix(size_t nrows, size_t ncols) const
virtual MutableMatrix * invert() const
virtual bool eigenvectors(MutableMatrix *eigenvals, MutableMatrix *eigenvecs, bool is_symm_or_hermitian) const
virtual M2_arrayintOrNull LU(MutableMatrix *L, MutableMatrix *U) const
virtual bool is_dense() const
virtual MutableMatrix * rowReducedEchelonForm() const
virtual size_t n_rows() const =0
virtual const Ring * get_ring() const =0
MatT * coerce()
Definition mat.hpp:151
MutableMatrix()
Definition mat.hpp:81
const MatT * coerce_const() const
Definition mat.hpp:159
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
mpfr_srcptr moveTo_gmpRR(mpfr_ptr _z)
Definition gmp-util.h:153
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
mpfr_srcptr gmp_RR
Definition m2-types.h:148
M2_arrayint M2_arrayintOrNull
Definition m2-types.h:99
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
engine_RawArrayIntPair engine_RawArrayIntPairOrNull
Definition m2-types.h:188
mpfr_srcptr gmp_RRorNull
Definition m2-types.h:149
bool QR(const Mat &A, Mat2 &Q, Mat3 &R, bool return_QR)
bool inverse(const Mat &A, Mat &result_inv)
the inverse of a square matrix
void determinant(const Mat &A, typename Mat::ElementType &result_det)
the determinant of a square matrix
bool eigenvaluesHermitian(const Mat &A, Mat2 &eigenvals)
size_t rowReducedEchelonForm(const Mat &A, Mat &result_rref)
the row reduced echelon form of a matrix over a field, or ZZ.
bool eigenvalues(const Mat &A, Mat2 &eigenvals)
M2_arrayintOrNull LUincremental(std::vector< size_t > &P, Mat &LU, const Mat &v, int i)
bool eigenvectors(const Mat &A, Mat2 &eigenvals, Mat3 &eigenvecs)
void subtractMultipleTo(DMatZZpFFPACK &C, const DMatZZpFFPACK &A, const DMatZZpFFPACK &B)
Definition dmat.cpp:63
size_t rank(const Mat &A)
the rank of a matrix
void addMultipleTo(DMatZZpFFPACK &C, const DMatZZpFFPACK::ElementType &a, const DMatZZpFFPACK &A, const DMatZZpFFPACK &B)
Definition dmat.cpp:13
M2_arrayintOrNull LU(const Mat &A, Mat &L, Mat &U)
bool SVD(const Mat &A, Mat2 &Sigma, Mat &U, Mat &Vt, int strategy)
size_t nullSpace(const Mat &A, Mat &result_nullspace)
the null space of a matrix
void mult(const DMatZZpFFPACK &A, const DMatZZpFFPACK &B, DMatZZpFFPACK &C)
Definition dmat.cpp:72
void clean(gmp_RR epsilon, T &mat)
bool solveLinear(const Mat &A, const Mat &B, Mat &X)
solve AX=B, return true if the system has a solution.
bool leastSquares(const Mat &A, const Mat &B, Mat &X, bool assume_full_rank)
bool solveInvertible(const Mat &A, const Mat &B, Mat &X)
solve AX=B, where A is a square (invertible) matrix.
void increase_norm(gmp_RRmutable nm, const T &mat)
M2_arrayintOrNull rankProfile(const Mat &A, bool row_profile)
Returns either the row or column rank profile of A.
bool eigenvectorsHermitian(const Mat &A, Mat2 &eigenvals, Mat3 &eigenvecs)
void triangularSolve(Mat &Lv, Mat &x, int m, int strategy)
volatile int x
#define T
Definition table.c:13