Skip to content

Commit 0259fc8

Browse files
Merge pull request #2422 from fredrik-johansson/polyinit
Fix initial value selection in acb_poly_find_roots for overlapping radii
2 parents 18bf8d8 + 993a6f7 commit 0259fc8

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

src/acb_poly/find_roots.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,17 @@ _acb_poly_roots_initial_values(acb_ptr roots, acb_srcptr poly, slong deg, slong
123123
flint_printf("initial values: radius %{mag} multiplicity %wd\n", r, m);
124124
#endif
125125

126-
/* pick m points on the circle with radius r */
126+
/* Pick m points on the circle with radius r */
127127
for (j = 0; j < m; j++)
128128
{
129-
theta = 6.283185307179586 * ((j + 1.0) / m + (double) i / deg) + 0.577216;
129+
/* Hack: the angle 2pi * ((j+1)/m + i/deg) distributes points uniformly
130+
when there are many radii. However, if two radii are
131+
very close, points can end up overlapping if (j+1)/m + i/deg
132+
happens to give the same fraction for two different i. Ensure
133+
that this doesn't happen. */
134+
double irrational_factor = 0.99071828182845905;
135+
136+
theta = 6.283185307179586 * (irrational_factor * (j + 1.0) / m + (double) i / deg) + 0.577216;
130137

131138
ri = roots + total;
132139
acb_zero(ri);

src/acb_poly/test/t-find_roots.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,34 @@ TEST_FUNCTION_START(acb_poly_find_roots, state)
8585
acb_poly_clear(C);
8686
}
8787

88+
/* Check that #2421 is fixed */
89+
{
90+
acb_poly_t f;
91+
acb_ptr roots;
92+
acb_t c;
93+
94+
acb_poly_init(f);
95+
acb_init(c);
96+
roots = _acb_vec_init(4);
97+
98+
acb_poly_set_coeff_si(f, 0, 10);
99+
acb_poly_set_coeff_si(f, 1, -170);
100+
acb_poly_set_coeff_si(f, 2, 2890);
101+
acb_poly_set_coeff_si(f, 3, -49130);
102+
acb_poly_set_coeff_si(f, 4, 835210);
103+
acb_set_ui(c, 83521);
104+
acb_poly_scalar_div(f, f, c, 64);
105+
106+
if (acb_poly_find_roots(roots, f, NULL, 40, 64) != 4)
107+
{
108+
flint_printf("FAIL: geometric example\n");
109+
flint_abort();
110+
}
111+
112+
_acb_vec_clear(roots, 4);
113+
acb_poly_clear(f);
114+
acb_clear(c);
115+
}
116+
88117
TEST_FUNCTION_END(state);
89118
}

src/python/flint_ctypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5422,9 +5422,9 @@ def roots(self, domain=None):
54225422
>>> f.roots(domain=QQbar) # complex algebraic roots
54235423
([Root a = 1.00000*I of a^2+1, Root a = -1.00000*I of a^2+1, Root a = 1.41421 of a^2-2, Root a = -1.41421 of a^2-2, -3/2], [1, 1, 1, 1, 2])
54245424
>>> f.roots(domain=RR) # real ball roots
5425-
([[-1.414213562373095 +/- 4.91e-17], [1.414213562373095 +/- 4.91e-17], -1.500000000000000], [1, 1, 2])
5425+
([[-1.414213562373095 +/- 4.89e-17], [1.414213562373095 +/- 4.89e-17], -1.500000000000000], [1, 1, 2])
54265426
>>> f.roots(domain=CC) # complex ball roots
5427-
([[-1.414213562373095 +/- 4.91e-17], [1.414213562373095 +/- 4.91e-17], ([+/- 1.45e-19] + [1.000000000000000 +/- 2.7e-19]*I), ([+/- 1.45e-19] + [-1.000000000000000 +/- 2.7e-19]*I), -1.500000000000000], [1, 1, 1, 1, 2])
5427+
([[-1.414213562373095 +/- 4.89e-17], [1.414213562373095 +/- 4.89e-17], ([+/- 1.45e-19] + [1.000000000000000 +/- 2.7e-19]*I), ([+/- 1.45e-19] + [-1.000000000000000 +/- 2.7e-19]*I), -1.500000000000000], [1, 1, 1, 1, 2])
54285428
>>> f.roots(RF) # real floating-point roots
54295429
([-1.414213562373095, 1.414213562373095, -1.500000000000000], [1, 1, 2])
54305430
>>> f.roots(CF) # complex floating-point roots

0 commit comments

Comments
 (0)