Repository: scipy/scipy

Issue:
BUG: typo in specfun.f?
### Describe your issue.

In `SUBROUTINE GAM0`, this looks suspicious:

```fortran
        GR=(25)
        DO 20 K=24,1,-1
20         GR=GR*X+G(K)
```

I wonder if that first line should be `GR=G(25)`.

### Reproducing Code Example

```python
na
```


### Error message

```shell
na
```


### SciPy/NumPy/Python version and system information

```shell
na
```



Discussion:
Yes it is a typo but we are not using it. The correct one for some other domain can be found as `GAMMA2` in the same file. 

EDIT: I think we are using it through `lamv` but not sure where. I'll check.
Looks like we are using this in `scipy.special.lmbda` but apparently I unconsciously fixed it during my C rewrite. I'll send the PR which will fix this soon. Thanks for catching this @jacobwilliams 

Resolving patch:
diff --git a/scipy/special/_basic.py b/scipy/special/_basic.py
--- a/scipy/special/_basic.py
+++ b/scipy/special/_basic.py
@@ -8,9 +8,8 @@
 import warnings
 from collections import defaultdict
 from heapq import heapify, heappop
-from numpy import (pi, asarray, floor, isscalar, iscomplex, real,
-                   imag, sqrt, where, mgrid, sin, place, issubdtype,
-                   extract, inexact, nan, zeros, sinc)
+from numpy import (pi, asarray, floor, isscalar, iscomplex, sqrt, where, mgrid,
+                   sin, place, issubdtype, extract, inexact, nan, zeros, sinc)
 from . import _ufuncs
 from ._ufuncs import (mathieu_a, mathieu_b, iv, jv, gamma,
                       psi, hankel1, hankel2, yv, kv, poch, binom,
@@ -781,10 +780,10 @@ def y1p_zeros(nt, complex=False):
     >>> from scipy.special import y1p_zeros
     >>> y1grad_roots, y1_values = y1p_zeros(4)
     >>> with np.printoptions(precision=5):
-    ...     print(f"Y1' Roots: {y1grad_roots}")
-    ...     print(f"Y1 values: {y1_values}")
-    Y1' Roots: [ 3.68302+0.j  6.9415 +0.j 10.1234 +0.j 13.28576+0.j]
-    Y1 values: [ 0.41673+0.j -0.30317+0.j  0.25091+0.j -0.21897+0.j]
+    ...     print(f"Y1' Roots: {y1grad_roots.real}")
+    ...     print(f"Y1 values: {y1_values.real}")
+    Y1' Roots: [ 3.68302  6.9415  10.1234  13.28576]
+    Y1 values: [ 0.41673 -0.30317  0.25091 -0.21897]
 
     `y1p_zeros` can be used to calculate the extremal points of :math:`Y_1`
     directly. Here we plot :math:`Y_1` and the first four extrema.
@@ -1595,7 +1594,7 @@ def mathieu_even_coef(m, q):
 
     .. math:: \mathrm{ce}_{2n}(z, q) = \sum_{k=0}^{\infty} A_{(2n)}^{(2k)} \cos 2kz
 
-    .. math:: \mathrm{ce}_{2n+1}(z, q) = 
+    .. math:: \mathrm{ce}_{2n+1}(z, q) =
               \sum_{k=0}^{\infty} A_{(2n+1)}^{(2k+1)} \cos (2k+1)z
 
     This function returns the coefficients :math:`A_{(2n)}^{(2k)}` for even
@@ -1856,7 +1855,7 @@ def clpmn(m, n, z, type=3):
                 fixarr = where(mf > nf, 0.0, gamma(nf-mf+1) / gamma(nf+mf+1))
     else:
         mp = m
-    p, pd = _specfun.clpmn(mp, n, real(z), imag(z), type)
+    p, pd = _specfun.clpmn(mp, n, z, type)
     if (m < 0):
         p = p * fixarr
         pd = pd * fixarr
@@ -3204,7 +3203,7 @@ def stirling2(N, K, *, exact=False):
 
     The values this function returns are calculated using a dynamic
     program which avoids redundant computation across the subproblems
-    in the solution. For array-like input, this implementation also 
+    in the solution. For array-like input, this implementation also
     avoids redundant computation across the different Stirling number
     calculations.
 


Test patch:
diff --git a/scipy/special/tests/meson.build b/scipy/special/tests/meson.build
--- a/scipy/special/tests/meson.build
+++ b/scipy/special/tests/meson.build
@@ -40,6 +40,7 @@ python_sources = [
   'test_round.py',
   'test_sf_error.py',
   'test_sici.py',
+  'test_specfun.py',
   'test_spence.py',
   'test_spfun_stats.py',
   'test_sph_harm.py',
diff --git a/scipy/special/tests/test_basic.py b/scipy/special/tests/test_basic.py
--- a/scipy/special/tests/test_basic.py
+++ b/scipy/special/tests/test_basic.py
@@ -3505,6 +3505,17 @@ def test_legendre(self):
         assert_almost_equal(leg4.c, array([35,0,-30,0,3])/8.0)
         assert_almost_equal(leg5.c, array([63,0,-70,0,15,0])/8.0)
 
+    @pytest.mark.parametrize('n', [1, 2, 3, 4, 5])
+    @pytest.mark.parametrize('zr', [0.5241717, 12.80232, -9.699001,
+                                    0.5122437, 0.1714377])
+    @pytest.mark.parametrize('zi', [9.766818, 0.2999083, 8.24726, -22.84843,
+                                    -0.8792666])
+    def test_lpn_against_clpmn(self, n, zr, zi):
+        reslpn = special.lpn(n, zr + zi*1j)
+        resclpmn = special.clpmn(0, n, zr+zi*1j)
+        assert_allclose(reslpn[0], resclpmn[0][0])
+        assert_allclose(reslpn[1], resclpmn[1][0])
+
 
 class TestLambda:
     def test_lmbda(self):
@@ -3737,6 +3748,15 @@ def test_pbvv_gradient(self):
         dp = (special.pbvv(eta, x + eps)[0] - special.pbvv(eta, x - eps)[0]) / eps / 2.
         assert_allclose(p[1], dp, rtol=1e-6, atol=1e-6)
 
+    def test_pbvv_seq(self):
+        res1, res2 = special.pbvv_seq(2, 3)
+        assert_allclose(res1, np.array([2.976319645712036,
+                                        1.358840996329579,
+                                        0.5501016716383508]))
+        assert_allclose(res2, np.array([3.105638472238475,
+                                        0.9380581512176672,
+                                        0.533688488872053]))
+
 
 class TestPolygamma:
     # from Table 6.2 (pg. 271) of A&S
diff --git a/scipy/special/tests/test_specfun.py b/scipy/special/tests/test_specfun.py
new file mode 100644
--- /dev/null
+++ b/scipy/special/tests/test_specfun.py
@@ -0,0 +1,36 @@
+"""
+Various made-up tests to hit different branches of the code in specfun.c
+"""
+
+import numpy as np
+from numpy.testing import assert_allclose
+from scipy import special
+
+
+def test_cchg_branches():
+    res = special.hyp1f1(0.1, 1, 7.0-24.0j)
+    assert_allclose(res, (-3.7659844658568016+4.970311359851648j))
+
+
+def test_cva2_cv0_branches():
+    res, resp = special.mathieu_cem([40, 129], [13, 14], [30, 45])
+    assert_allclose(res, np.array([-0.3741211, 0.74441928]))
+    assert_allclose(resp, np.array([-37.02872758, -86.13549877]))
+
+    res, resp = special.mathieu_sem([40, 129], [13, 14], [30, 45])
+    assert_allclose(res, np.array([0.92955551, 0.66771207]))
+    assert_allclose(resp, np.array([-14.91073448, 96.02954185]))
+
+
+def test_chgm_branches():
+    res = special.eval_genlaguerre(-3.2, 3, 2.5)
+    assert_allclose(res, -0.7077721935779854)
+
+
+def test_hygfz_branches():
+    """(z == 1.0) && (c-a-b > 0.0)"""
+    res = special.hyp2f1(1.5, 2.5, 4.5, 1.+0.j)
+    assert_allclose(res, 10.30835089459151+0j)
+    """(cabs(z+1) < eps) && (fabs(c-a+b - 1.0) < eps)"""
+    res = special.hyp2f1(5+5e-16, 2, 2, -1.0 + 5e-16j)
+    assert_allclose(res, 0.031249999999999986+3.9062499999999994e-17j)