Skip to content

Commit dd979a2

Browse files
committed
fundamental matrices
1 parent deeeda6 commit dd979a2

12 files changed

Lines changed: 529 additions & 43 deletions

File tree

doc/source/gr.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ Flags can be OR'ed and checked only at the top level of a computation
175175
to avoid complex control flow::
176176

177177
status = GR_SUCCESS;
178-
gr |= gr_add(res, a, b, ctx);
179-
gr |= gr_pow_ui(res, res, 2, ctx);
178+
status |= gr_add(res, a, b, ctx);
179+
status |= gr_pow_ui(res, res, 2, ctx);
180180
...
181181

182182
If we do not care about recovering from *undefined*/*unknown* results,

examples/holonomic.c

Lines changed: 107 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#include "acb_types.h"
22
#include "acb_poly.h"
33
#include "acb_mat.h"
4-
#include "fmpq_types.h"
5-
#include "fmpq_poly.h"
64
#include "acb_holonomic.h"
5+
#include "gr.h"
6+
#include "gr_poly.h"
77

88

99
void
@@ -43,7 +43,7 @@ ordinary(void)
4343
acb_poly_set_coeff_si(ctx->dop + 1, 0, 2);
4444
acb_poly_set_coeff_si(ctx->dop + 0, 4, 7);
4545

46-
ctx->flags |= ACB_HOLONOMIC_WANT_SERIES;
46+
/* ctx->flags |= ACB_HOLONOMIC_WANT_SERIES; */
4747

4848
acb_holonomic_sum_ordinary(ctx);
4949
acb_holonomic_sum_canonical_basis(ctx);
@@ -142,9 +142,14 @@ void
142142
whittaker_m(void) /* non-integer exponent, no logs */
143143
{
144144
acb_t kappa, mu2, half;
145+
acb_poly_t val;
146+
145147
acb_init(kappa);
146148
acb_init(mu2);
147149
acb_init(half);
150+
acb_poly_init(val);
151+
152+
acb_holonomic_sum_context_t ctx;
148153

149154
acb_set_si(kappa, 2);
150155
acb_set_si(mu2, 3);
@@ -154,8 +159,6 @@ whittaker_m(void) /* non-integer exponent, no logs */
154159
slong dop_order = 2;
155160
slong len = dop_order;
156161

157-
acb_holonomic_sum_context_t ctx;
158-
159162
acb_holonomic_sum_context_init(ctx, dop_order + 1, 1, 1, len);
160163

161164
acb_poly_set_coeff_si(ctx->dop + 2, 0, 4);
@@ -166,7 +169,7 @@ whittaker_m(void) /* non-integer exponent, no logs */
166169
acb_addmul_si((ctx->dop + 0)->coeffs + 0, mu2, -4, prec);
167170

168171
acb_sqrt(ctx->expo, mu2, prec);
169-
acb_add(ctx->expo, ctx->expo, half, prec); /* sub for other expo */
172+
acb_add(ctx->expo, ctx->expo, half, prec); /* other expo = mu2 - 1/2 */
170173

171174
ctx->sing_shifts[0].n = 0;
172175
ctx->sing_shifts[0].mult = 1;
@@ -180,38 +183,120 @@ whittaker_m(void) /* non-integer exponent, no logs */
180183

181184
acb_holonomic_sum_divconquer(ctx, prec);
182185

183-
flint_printf("(%{acb} + x)^(%{acb}) * (%{acb_poly})\n",
184-
ctx->pts, ctx->expo,
185-
acb_holonomic_sol_sum_ptr(ctx->sol, 0, 0));
186+
acb_poly_struct * f = acb_holonomic_sol_sum_ptr(ctx->sol, 0, 0);
186187

187-
acb_poly_t tmp;
188-
acb_poly_init(tmp);
189-
acb_poly_set_coeff_si(tmp, 1, 1);
190-
acb_poly_set_coeff_acb(tmp, 0, ctx->pts);
191-
acb_poly_pow_acb_series(tmp, tmp, ctx->expo, len, prec);
192-
acb_poly_mullow(tmp, tmp, acb_holonomic_sol_sum_ptr(ctx->sol, 0, 0), len, prec);
188+
flint_printf("(%{acb} + x)^(%{acb}) * (%{acb_poly})\n",
189+
ctx->pts, ctx->expo, f);
193190

194-
flint_printf("M(%{acb} + x) = %{acb_poly} + O(x^%wd)\n", ctx->pts, tmp, len);
191+
_acb_holonomic_sol_value(val, ctx->expo, f, ctx->sol[0].nlogs, ctx->pts,
192+
ctx->nder, 1, ctx->prec);
195193

196-
acb_poly_clear(tmp);
194+
flint_printf("M(%{acb} + x) = %{acb_poly} + O(x^%wd)\n", ctx->pts, val, len);
197195

198196
acb_holonomic_sum_context_clear(ctx);
199197
acb_clear(kappa);
200198
acb_clear(mu2);
201199
acb_clear(half);
200+
acb_poly_clear(val);
202201
}
203202

204203

205-
/* TODO once we have more support for extracting the results: Apéry */
204+
void
205+
fundamental_matrix(const char * dop_str,
206+
const acb_holonomic_exponents_struct * expos,
207+
double pt_d)
208+
{
209+
gr_ctx_t CC, Pol, Dop;
210+
gr_ptr dop;
211+
212+
slong prec = 30;
213+
214+
int status = GR_SUCCESS;
215+
216+
gr_ctx_init_complex_acb(CC, prec);
217+
gr_ctx_init_gr_poly(Pol, CC);
218+
gr_ctx_init_gr_poly(Dop, Pol); /* should be Ore poly */
219+
220+
GR_TMP_INIT(dop, Dop);
221+
222+
status |= gr_ctx_set_gen_name(Pol, "z");
223+
status |= gr_ctx_set_gen_name(Dop, "Tz");
224+
status |= gr_set_str(dop, dop_str, Dop);
225+
status |= gr_println(dop, Dop);
226+
GR_MUST_SUCCEED(status);
227+
228+
slong dop_order = gr_poly_length(dop, Dop) - 1;
229+
230+
acb_mat_t mat;
231+
acb_mat_init(mat, dop_order, dop_order);
232+
233+
acb_t pt;
234+
acb_init(pt);
235+
acb_set_d(pt, pt_d);
236+
237+
acb_holonomic_fundamental_matrix(mat, dop, Dop, expos, pt, 1, 0, 8, prec);
238+
239+
flint_printf("%{acb_mat}\n", mat);
240+
241+
acb_mat_clear(mat);
242+
GR_TMP_CLEAR(dop, Dop);
243+
gr_ctx_clear(Dop);
244+
gr_ctx_clear(Pol);
245+
gr_ctx_clear(CC);
246+
acb_clear(pt);
247+
}
248+
249+
250+
void
251+
apery(void)
252+
{
253+
acb_holonomic_shift_struct shift[1] = {{ .n = 0, .mult = 3 }};
254+
acb_holonomic_group_struct grp[1] = {{ .nshifts = 1, .shifts = shift }};
255+
acb_init(grp->expo);
256+
acb_zero(grp->expo);
257+
acb_holonomic_exponents_struct expos[1] = {{ .len = 1, .grps = grp }};
258+
259+
fundamental_matrix(
260+
"(z^2 - 34*z + 1)*Tz^3 + (3*z^2 - 51*z)*Tz^2 + (3*z^2 - 27*z)*Tz + z^2 - 5*z",
261+
expos,
262+
0.015625);
263+
264+
acb_clear(grp->expo);
265+
}
266+
267+
268+
void
269+
multiple_shifts(void)
270+
{
271+
/* const char * dop = "Tz^4 - 4*Tz^3 + 3*Tz^2 - z"; */
272+
const char * dop = "Tz^6 - 6*Tz^5 + 12*Tz^4 - 10*Tz^3 + 3*Tz^2 + z^2";
273+
274+
acb_holonomic_shift_struct shift[3] = {
275+
{ .n = 0, .mult = 2 },
276+
{ .n = 1, .mult = 3 },
277+
{ .n = 3, .mult = 1 },
278+
};
279+
acb_holonomic_group_struct grp[1] = {{ .nshifts = 3, .shifts = shift }};
280+
acb_init(grp->expo);
281+
acb_zero(grp->expo);
282+
acb_holonomic_exponents_struct expos[1] = {{ .len = 1, .grps = grp }};
283+
284+
fundamental_matrix(dop, expos, 2.);
285+
286+
acb_clear(grp->expo);
287+
}
206288

207289

208290
int
209291
main(void)
210292
{
211-
ordinary();
212-
series();
213-
bessel_j0();
214-
whittaker_m();
293+
/* ordinary(); */
294+
/* series(); */
295+
/* bessel_j0(); */
296+
/* whittaker_m(); */
297+
298+
/* apery(); */
299+
multiple_shifts();
215300

216301
flint_cleanup_master();
217302
}

src/acb_holonomic.h

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ typedef mp_limb_signed_t slong;
77
/* */
88

99
#include "acb_types.h"
10+
#include "gr_types.h"
1011

1112
#ifdef __cplusplus
1213
extern "C" {
@@ -21,6 +22,36 @@ typedef struct
2122
}
2223
acb_holonomic_shift_struct;
2324

25+
26+
typedef struct
27+
{
28+
acb_t expo;
29+
slong nshifts;
30+
acb_holonomic_shift_struct * shifts;
31+
}
32+
acb_holonomic_group_struct;
33+
34+
35+
typedef struct
36+
{
37+
slong len;
38+
acb_holonomic_group_struct * grps;
39+
}
40+
acb_holonomic_exponents_struct;
41+
42+
43+
typedef enum
44+
{
45+
ACB_HOLONOMIC_BASIS_ECHELON = 0,
46+
ACB_HOLONOMIC_BASIS_CASCADE /* XXX: same as Frobenius? */
47+
}
48+
acb_holonomic_basis_t;
49+
50+
51+
slong acb_holonomic_group_length(const acb_holonomic_group_struct * grp);
52+
53+
/****************************************************************************/
54+
2455
typedef struct
2556
{
2657
acb_mat_t extini;
@@ -70,6 +101,11 @@ _acb_holonomic_sol_add_term(
70101
const fmpz * binom_n,
71102
slong nder, slong prec, slong sums_prec);
72103

104+
void _acb_holonomic_sol_value(acb_poly_struct * val, acb_srcptr expo,
105+
const acb_poly_struct * sums, slong nlogs,
106+
acb_srcptr pt, slong nder,
107+
slong nshifts, slong prec);
108+
73109
/****************************************************************************/
74110

75111
/* XXX see if this can be reused by other summation algorithms (probably not as
@@ -80,7 +116,7 @@ _acb_holonomic_sol_add_term(
80116
typedef struct
81117
{
82118
/* operator */
83-
acb_poly_struct * dop;
119+
acb_poly_struct * dop; /* XXX FJ: move outside the struct? */
84120
slong dop_len;
85121
slong dop_clen;
86122

@@ -127,15 +163,44 @@ void acb_holonomic_sum_context_init(
127163
void acb_holonomic_sum_context_clear(acb_holonomic_sum_context_struct * ctx);
128164

129165
void acb_holonomic_sum_ordinary(acb_holonomic_sum_context_struct * ctx);
130-
void acb_holonomic_sum_mum(acb_holonomic_sum_context_struct * ctx);
131166
void acb_holonomic_sum_canonical_basis(acb_holonomic_sum_context_struct * ctx);
167+
void acb_holonomic_sum_highest(acb_holonomic_sum_context_struct * ctx);
168+
void acb_holonomic_sum_group(acb_holonomic_sum_context_struct * ctx, const acb_holonomic_group_struct * grp);
169+
132170

133171
void _acb_holonomic_sum_precompute(acb_holonomic_sum_context_struct * ctx);
134172
void _acb_holonomic_sum_reset(acb_holonomic_sum_context_struct * ctx);
135173

136174
void acb_holonomic_sum_divconquer(
137175
acb_holonomic_sum_context_struct * ctx, slong nterms);
138176

177+
void acb_holonomic_sum_value(acb_poly_struct * val, slong nfrobshifts,
178+
const acb_holonomic_sum_context_struct * ctx,
179+
slong i, slong j, slong prec);
180+
181+
/****************************************************************************/
182+
183+
/* XXX void * data or fix args */
184+
typedef void (* acb_holonomic_sum_worker_t)(
185+
acb_holonomic_sum_context_struct * ctx, slong nterms);
186+
187+
void _acb_holonomic_fundamental_matrix(
188+
acb_mat_struct * mat,
189+
const acb_poly_struct * dop, slong dop_len,
190+
const acb_holonomic_group_struct * groups, slong ngroups,
191+
acb_srcptr pts, slong npts,
192+
acb_holonomic_basis_t basis,
193+
acb_holonomic_sum_worker_t sum_worker,
194+
slong nterms, slong prec);
195+
196+
int acb_holonomic_fundamental_matrix(
197+
acb_mat_struct * mat,
198+
gr_srcptr dop, gr_ctx_t dop_ctx,
199+
const acb_holonomic_exponents_struct * expos,
200+
acb_srcptr pts, slong npts,
201+
acb_holonomic_basis_t basis,
202+
slong nterms, slong prec);
203+
139204
/****************************************************************************/
140205

141206
void _acb_holonomic_apply_diffop_basecase_weights(
@@ -147,7 +212,7 @@ void _acb_holonomic_apply_diffop_basecase_weights(
147212

148213
void _acb_holonomic_apply_diffop_basecase_precomp(
149214
acb_poly_struct * g, slong goff,
150-
acb_srcptr weights,
215+
acb_srcptr weights, slong weights_nlogs,
151216
const acb_poly_struct * f, slong foff, slong flen,
152217
slong nlogs,
153218
slong start, slong len,

src/acb_holonomic/apply_diffop_basecase.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ _acb_holonomic_apply_diffop_basecase_weights(
105105
void
106106
_acb_holonomic_apply_diffop_basecase_precomp(
107107
acb_poly_struct * g, slong goff,
108-
acb_srcptr weights,
108+
acb_srcptr weights, slong weights_nlogs,
109109
const acb_poly_struct * f, slong foff, slong flen,
110110
slong nlogs,
111111
slong start, slong len,
@@ -121,7 +121,7 @@ _acb_holonomic_apply_diffop_basecase_precomp(
121121
for (slong k = k1; k < nlogs; k++)
122122
{
123123
acb_srcptr src = (f + k)->coeffs + foff;
124-
acb_srcptr cofac = weights + p1 * nlogs * flen + (k - k1) * flen;
124+
acb_srcptr cofac = weights + p1 * weights_nlogs * flen + (k - k1) * flen;
125125
slong fklen = FLINT_MIN(flen, (f + k)->length - foff);
126126
/* loop on p */
127127
acb_dot(dest, dest, 0, cofac, 1, src, 1, fklen, prec);
@@ -155,7 +155,7 @@ acb_holonomic_apply_diffop_basecase(
155155
_acb_poly_vec_fit_length(g, nlogs, len);
156156
_acb_holonomic_apply_diffop_basecase_precomp(
157157
g, 0,
158-
weights, f, 0, flen,
158+
weights, nlogs, f, 0, flen,
159159
nlogs, start, len, prec);
160160
_acb_poly_vec_set_length(g, nlogs, len);
161161
_acb_poly_vec_normalise(g, nlogs);

src/acb_holonomic/exponents.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "acb_holonomic.h"
2+
3+
4+
slong
5+
acb_holonomic_group_length(const acb_holonomic_group_struct * grp)
6+
{
7+
slong len = 0;
8+
9+
for (slong s = 0; s < grp->nshifts; s++)
10+
len += grp->shifts[s].mult;
11+
12+
return len;
13+
}
14+
15+
16+
void
17+
acb_holonomic_exponents_init(acb_holonomic_exponents_struct * expos)
18+
{
19+
expos->len = 0;
20+
expos->grps = NULL;
21+
}
22+
23+
24+
void
25+
acb_holonomic_exponents_free(acb_holonomic_exponents_struct * expos)
26+
{
27+
flint_free(expos->grps);
28+
}
29+
30+
31+
32+

0 commit comments

Comments
 (0)