1 /*
2 * This file is part of MPSolve 3.2.1
3 *
4 * Copyright (C) 2001-2020, Dipartimento di Matematica "L. Tonelli", Pisa.
5 * License: http://www.gnu.org/licenses/gpl.html GPL version 3 or higher
6 *
7 * Authors:
8 * Leonardo Robol <leonardo.robol@unipi.it>
9 */
10
11 #include <mps/mps.h>
12 #include <string.h>
13
14 mps_monomial_matrix_poly*
mps_monomial_matrix_poly_new(mps_context * ctx,int degree,int m,mps_boolean monic)15 mps_monomial_matrix_poly_new (mps_context * ctx, int degree, int m, mps_boolean monic)
16 {
17 mps_monomial_matrix_poly * poly = mps_new (mps_monomial_matrix_poly);
18
19 MPS_POLYNOMIAL (poly)->degree = degree * m;
20 mps_polynomial_init (ctx, MPS_POLYNOMIAL (poly));
21
22 /* Matrix polynomial specific fields */
23 poly->monic = monic;
24 poly->m = m;
25 poly->degree = degree;
26
27 /* Allocation of the necessary memory to hold all the matrices. */
28 poly->P = mps_newv (cplx_t, poly->m * poly->m * (degree + 1));
29 poly->mP = mps_newv (mpc_t, poly->m * poly->m * (degree + 1));
30 poly->mpqPr = mps_newv (mpq_t, poly->m * poly->m * (degree + 1));
31 poly->mpqPi = mps_newv (mpq_t, poly->m * poly->m * (degree + 1));
32
33 mpc_vinit2 (poly->mP, poly->m * poly->m * (degree + 1), ctx->mpwp);
34 mpq_vinit (poly->mpqPr, poly->m * poly->m * (degree + 1));
35 mpq_vinit (poly->mpqPi, poly->m * poly->m * (degree + 1));
36
37 MPS_POLYNOMIAL (poly)->type_name = "mps_monomial_matrix_poly";
38 MPS_POLYNOMIAL (poly)->thread_safe = false;
39
40 MPS_POLYNOMIAL (poly)->structure = MPS_STRUCTURE_UNKNOWN;
41
42 /* Setup the overloaded methods for our matrix polynomial */
43 MPS_POLYNOMIAL (poly)->free = mps_monomial_matrix_poly_free;
44 MPS_POLYNOMIAL (poly)->raise_data = mps_monomial_matrix_poly_raise_data;
45 MPS_POLYNOMIAL (poly)->meval = mps_monomial_matrix_poly_meval;
46
47 return poly;
48 }
49
50 void
mps_monomial_matrix_poly_free(mps_context * ctx,mps_polynomial * poly)51 mps_monomial_matrix_poly_free (mps_context * ctx, mps_polynomial * poly)
52 {
53 mps_monomial_matrix_poly * mpoly = MPS_MONOMIAL_MATRIX_POLY (poly);
54
55 free (mpoly->P);
56
57 mpc_vclear (mpoly->mP, mpoly->m * (poly->degree + mpoly->m));
58 free (mpoly->mP);
59
60 mpq_vclear (mpoly->mpqPr, mpoly->m * (poly->degree + mpoly->m));
61 free (mpoly->mpqPr);
62
63 mpq_vclear (mpoly->mpqPi, mpoly->m * (poly->degree + mpoly->m));
64 free (mpoly->mpqPi);
65
66 free (poly);
67 }
68
mps_monomial_matrix_poly_add_flags(mps_context * ctx,mps_monomial_matrix_poly * mpoly,int flags)69 void mps_monomial_matrix_poly_add_flags (mps_context * ctx,
70 mps_monomial_matrix_poly * mpoly,
71 int flags)
72 {
73 mpoly->flags |= flags;
74 }
75
76
mps_monomial_matrix_poly_clear_flags(mps_context * ctx,mps_monomial_matrix_poly * mpoly,int flags)77 void mps_monomial_matrix_poly_clear_flags (mps_context * ctx,
78 mps_monomial_matrix_poly * mpoly,
79 int flags)
80 {
81 mpoly->flags &= ~flags;
82 }
83
84
85 void
mps_monomial_matrix_poly_set_coefficient_d(mps_context * ctx,mps_monomial_matrix_poly * mpoly,int i,cplx_t * matrix)86 mps_monomial_matrix_poly_set_coefficient_d (mps_context * ctx,
87 mps_monomial_matrix_poly *mpoly,
88 int i,
89 cplx_t * matrix)
90 {
91 mps_polynomial *poly = MPS_POLYNOMIAL (mpoly);
92 int degree = poly->degree;
93 int j;
94
95 if (i < 0 || i > degree)
96 {
97 mps_error (ctx, "Degree of the coefficient is out of bounds");
98 return;
99 }
100
101 if (poly->structure == MPS_STRUCTURE_UNKNOWN)
102 {
103 poly->structure = MPS_STRUCTURE_REAL_FP;
104 }
105 else if (!MPS_STRUCTURE_IS_FP (poly->structure))
106 {
107 mps_error (ctx, "Cannot assign floating point coefficients to a non-floating-point polynomial.");
108 return;
109 }
110
111 /* Copy the data in the coefficients. Please note that we are assuming
112 * row-major order in here. */
113 cplx_t *ptr = mpoly->P + (mpoly->m * mpoly->m) * i;
114 memmove (ptr, matrix, sizeof(cplx_t) * (mpoly->m * mpoly->m));
115
116 for (j = 0; j < mpoly->m * mpoly->m; j++)
117 {
118 /* Adjust structure if needed */
119 if (cplx_Im (matrix[j]) != 0.0)
120 poly->structure = MPS_STRUCTURE_COMPLEX_FP;
121
122 mpc_set_cplx (mpoly->mP[j], mpoly->P[j]);
123 }
124 }
125
126 void
mps_monomial_matrix_poly_set_coefficient_q(mps_context * ctx,mps_monomial_matrix_poly * mpoly,int i,mpq_t * matrix_r,mpq_t * matrix_i)127 mps_monomial_matrix_poly_set_coefficient_q (mps_context * ctx,
128 mps_monomial_matrix_poly *mpoly,
129 int i,
130 mpq_t * matrix_r,
131 mpq_t * matrix_i)
132 {
133 mps_polynomial *poly = MPS_POLYNOMIAL (mpoly);
134 int degree = poly->degree;
135 int j;
136
137 if (i < 0 || i > degree)
138 {
139 mps_error (ctx, "Degree of the coefficient is out of bounds");
140 return;
141 }
142
143 if (poly->structure == MPS_STRUCTURE_UNKNOWN)
144 poly->structure = MPS_STRUCTURE_REAL_RATIONAL;
145
146 if (MPS_STRUCTURE_IS_FP (poly->structure))
147 {
148 mps_error (ctx, "Cannot assign exact coefficients to a floating point polynomial.");
149 return;
150 }
151
152 for (j = 0; j < mpoly->m * mpoly->m; j++)
153 {
154 mpq_set (mpoly->mpqPr[i], matrix_r[i]);
155 mpq_set (mpoly->mpqPi[i], matrix_i[i]);
156
157 if (mpq_cmp_ui (matrix_i[i], 0U, 1U) != 0)
158 poly->structure = MPS_STRUCTURE_COMPLEX_RATIONAL;
159 }
160 }
161
162 mps_boolean
mps_monomial_matrix_poly_meval(mps_context * ctx,mps_polynomial * poly,mpc_t x,mpc_t value,rdpe_t error)163 mps_monomial_matrix_poly_meval (mps_context * ctx, mps_polynomial * poly,
164 mpc_t x, mpc_t value, rdpe_t error)
165 {
166 mps_monomial_matrix_poly *mpoly = MPS_MONOMIAL_MATRIX_POLY (poly);
167
168 if (!mpoly->flags & MPS_MONOMIAL_MATRIX_POLY_HESSENBERG)
169 {
170 /* TODO: Insert the necessary steps to make a Hessenberg matrix
171 * available in place of this non-Hessenberg matrix polynomial. */
172 }
173
174 /* TODO: This is not thread safe - at all! Insert a double buffer strategy
175 * in here, as for the case of mps_monomial_poly. */
176 if (mpc_get_prec (mpoly->mP[0]) < mpc_get_prec (value))
177 mps_monomial_matrix_poly_raise_data (ctx, poly, mpc_get_prec (value));
178
179 /* Otherwise just proceed with Horner and our recursive implementation. */
180 /* TODO: We are performing a floating point evaluation here, just for simplicity. */
181 mps_mhessenberg_shifted_determinant (ctx, mpoly->mP, x, mpoly->m, value, error);
182
183 return true;
184 }
185
186 long int
mps_monomial_matrix_poly_raise_data(mps_context * ctx,mps_polynomial * p,long int wp)187 mps_monomial_matrix_poly_raise_data (mps_context * ctx,
188 mps_polynomial * p,
189 long int wp)
190 {
191 int i;
192 mps_monomial_matrix_poly *mpoly = MPS_MONOMIAL_MATRIX_POLY (p);
193 size_t n_elems = (mpoly->degree + 1) * (mpoly->m * mpoly->m);
194
195 for (i = 0; i < n_elems; i++)
196 {
197 mpc_set_prec (mpoly->mP[i], wp);
198 }
199
200 if (MPS_STRUCTURE_IS_INTEGER (p->structure) ||
201 MPS_STRUCTURE_IS_RATIONAL (p->structure))
202 {
203 mpc_set_q (mpoly->mP[i], mpoly->mpqPr[i], mpoly->mpqPi[i]);
204 }
205
206 return mpc_get_prec (mpoly->mP[0]);
207 }
208