Skip to content

Commit cf3d28f

Browse files
j-bowhaymdhaber
andauthored
ENH: linalg.funm: Pythranize double for loop (scipy#21440)
* ENH: linalg.funm: pythranize loops in `linalg.funm` Reviewed at scipy#21440 --------- Co-authored-by: Matt Haberland <[email protected]> Co-authored-by: Jake Bowhay <[email protected]>
1 parent 04ec412 commit cf3d28f

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

scipy/linalg/_linalg_pythran.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pythran export _funm_loops(float32[:, :], float32[:, :], int, float32)
2+
#pythran export _funm_loops(float64[:, :], float64[:, :], int, float64)
3+
#pythran export _funm_loops(complex64[:, :], complex64[:, :], int, float32)
4+
#pythran export _funm_loops(complex128[:, :], complex128[:, :], int, float64)
5+
def _funm_loops(F, T, n, minden):
6+
for p in range(1, n):
7+
for i in range(1, n - p + 1):
8+
j = i + p
9+
s = T[i - 1, j - 1] * (F[j - 1, j - 1] - F[i - 1, i - 1])
10+
val = (sum(T[i - 1, i:j - 1] * F[i:j - 1, j - 1])
11+
- sum(F[i - 1, i:j - 1] * T[i:j - 1, j - 1]))
12+
s = s + val
13+
den = T[j - 1, j - 1] - T[i - 1, i - 1]
14+
15+
if den != 0.0:
16+
s = s / den
17+
18+
F[i - 1, j - 1] = s
19+
minden = min(minden, abs(den))
20+
return F, minden

scipy/linalg/_matfuncs.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from ._expm_frechet import expm_frechet, expm_cond
1717
from ._matfuncs_sqrtm import sqrtm
1818
from ._matfuncs_expm import pick_pade_structure, pade_UV_calc
19+
from ._linalg_pythran import _funm_loops # type: ignore[import-not-found]
1920

2021
__all__ = ['expm', 'cosm', 'sinm', 'tanm', 'coshm', 'sinhm', 'tanhm', 'logm',
2122
'funm', 'signm', 'sqrtm', 'fractional_matrix_power', 'expm_frechet',
@@ -685,18 +686,7 @@ def funm(A, func, disp=True):
685686

686687
# implement Algorithm 11.1.1 from Golub and Van Loan
687688
# "matrix Computations."
688-
for p in range(1, n):
689-
for i in range(1, n-p+1):
690-
j = i + p
691-
s = T[i-1, j-1] * (F[j-1, j-1] - F[i-1, i-1])
692-
ksl = slice(i, j-1)
693-
val = dot(T[i-1, ksl], F[ksl, j-1]) - dot(F[i-1, ksl], T[ksl, j-1])
694-
s = s + val
695-
den = T[j-1, j-1] - T[i-1, i-1]
696-
if den != 0.0:
697-
s = s / den
698-
F[i-1, j-1] = s
699-
minden = min(minden, abs(den))
689+
F, minden = _funm_loops(F, T, n, minden)
700690

701691
F = dot(dot(Z, F), transpose(conjugate(Z)))
702692
F = _maybe_real(A, F)

scipy/linalg/meson.build

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,22 @@ _cythonized_array_utils = py3.extension_module('_cythonized_array_utils',
205205
subdir: 'scipy/linalg'
206206
)
207207

208+
if use_pythran
209+
py3.extension_module('_linalg_pythran',
210+
pythran_gen.process('_linalg_pythran.py'),
211+
cpp_args: cpp_args_pythran,
212+
dependencies: [pythran_dep, np_dep],
213+
link_args: version_link_args,
214+
install: true,
215+
subdir: 'scipy/linalg'
216+
)
217+
else
218+
py3.install_sources(
219+
['_linalg_pythran.py'],
220+
subdir: 'scipy/linalg'
221+
)
222+
endif
223+
208224

209225
python_sources = [
210226
'__init__.py',

0 commit comments

Comments
 (0)