|
1 | | -# slicot_compat.py - compatibility wrappers for slicot package |
| 1 | +# slicot_compat.py - compatibility wrappers for slicot/slycot packages |
2 | 2 | # |
3 | 3 | # This module provides wrappers around the slicot package functions to match |
4 | | -# the API used by the older slycot package. This allows python-control to |
5 | | -# use slicot (C11 translation with Python bindings) as a drop-in replacement. |
| 4 | +# the API used by the older slycot package. It also supports falling back to |
| 5 | +# slycot if slicot is not installed. |
6 | 6 |
|
7 | | -"""Compatibility layer for slicot package. |
| 7 | +"""Compatibility layer for slicot/slycot packages. |
8 | 8 |
|
9 | 9 | This module wraps slicot functions to match the slycot API, minimizing changes |
10 | | -to existing code in python-control. |
| 10 | +to existing code in python-control. If slicot is not installed, it falls back |
| 11 | +to using slycot directly. |
11 | 12 | """ |
12 | 13 |
|
13 | | -import slicot # noqa: F401 - import at top level so ImportError is raised early |
14 | 14 | import numpy as np |
15 | 15 |
|
16 | 16 | from .exception import ControlArgument |
17 | 17 |
|
| 18 | +# Try to import slicot first (preferred), fall back to slycot |
| 19 | +_use_slicot = False |
| 20 | +_use_slycot = False |
| 21 | + |
| 22 | +try: |
| 23 | + import slicot # noqa: F401 |
| 24 | + _use_slicot = True |
| 25 | +except ImportError: |
| 26 | + try: |
| 27 | + import slycot # noqa: F401 |
| 28 | + _use_slycot = True |
| 29 | + except ImportError: |
| 30 | + pass |
| 31 | + |
| 32 | +if not _use_slicot and not _use_slycot: |
| 33 | + raise ImportError("Neither slicot nor slycot is installed") |
| 34 | + |
18 | 35 | __all__ = [ |
19 | 36 | 'SlicotResultWarning', 'SlicotArithmeticError', |
20 | 37 | 'sb03md', 'sb03od', 'sb04md', 'sb04qd', 'sg03ad', |
@@ -1087,3 +1104,19 @@ def mb03rd(n, A, X, pmax=1.0, tol=0.0, ldwork=None): |
1087 | 1104 | w = wr + 1j * wi |
1088 | 1105 |
|
1089 | 1106 | return Aout, Xout, blsize[:nblcks], w |
| 1107 | + |
| 1108 | + |
| 1109 | +# If using slycot (not slicot), overwrite with direct imports from slycot |
| 1110 | +if _use_slycot and not _use_slicot: |
| 1111 | + from slycot import ( # noqa: F811 |
| 1112 | + sb03md, sb03od, sb04md, sb04qd, sg03ad, |
| 1113 | + sb02md, sb02mt, sg02ad, sb01bd, |
| 1114 | + sb10ad, sb10hd, ab08nd, |
| 1115 | + ab09ad, ab09md, ab09nd, |
| 1116 | + ab13bd, ab13dd, ab13md, |
| 1117 | + tb01pd, tb04ad, tb05ad, td04ad, mb03rd, |
| 1118 | + ) |
| 1119 | + from slycot.exceptions import ( # noqa: F811 |
| 1120 | + SlycotResultWarning as SlicotResultWarning, |
| 1121 | + SlycotArithmeticError as SlicotArithmeticError, |
| 1122 | + ) |
0 commit comments