Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pip install .

SCS supports several linear solver backends. The default is `AUTO`, which
selects the best available solver for the platform:
- **macOS**: Apple Accelerate if available, otherwise QDLDL
- **macOS**: QDLDL (Apple Accelerate is available via `LinearSolver.ACCELERATE`)
- **Linux / Windows**: MKL Pardiso if available, otherwise QDLDL

```python
Expand Down
15 changes: 6 additions & 9 deletions scs/py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,12 @@ def _load_module(name):
def _resolve_auto():
"""Auto-detect the best available direct solver for this platform."""
if sys.platform == "darwin":
try:
return _load_module("_scs_accelerate")
except ImportError:
pass
else:
try:
return _load_module("_scs_mkl")
except ImportError:
pass
# Prefer the bundled QDLDL on macOS over Apple Accelerate.
return _scs_direct
try:
return _load_module("_scs_mkl")
except ImportError:
pass
return _scs_direct


Expand Down
35 changes: 8 additions & 27 deletions test/test_scs_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3249,23 +3249,20 @@ def fail_import(name):


@pytest.mark.thread_unsafe(reason="patches module-level scs._load_module / scs.sys")
def test_resolve_auto_darwin_tries_accelerate():
"""On macOS, AUTO should try _scs_accelerate first."""
from unittest.mock import patch, MagicMock
from scs import _resolve_auto

fake_accel = MagicMock()
def test_resolve_auto_darwin_prefers_qdldl():
"""On macOS, AUTO should return QDLDL without attempting Accelerate."""
from unittest.mock import patch
from scs import _resolve_auto, _scs_direct

def mock_load(name):
if name == "_scs_accelerate":
return fake_accel
def fail_import(name):
raise ImportError(f"mocked: {name}")

with patch("scs.sys") as mock_sys:
mock_sys.platform = "darwin"
with patch("scs._load_module", side_effect=mock_load):
with patch("scs._load_module", side_effect=fail_import) as mock_load:
module = _resolve_auto()
assert module is fake_accel
assert module is _scs_direct
mock_load.assert_not_called()


@pytest.mark.thread_unsafe(reason="patches module-level scs._load_module / scs.sys")
Expand Down Expand Up @@ -3308,22 +3305,6 @@ def mock_load(name):
assert module is fake_mkl


@pytest.mark.thread_unsafe(reason="patches module-level scs._load_module / scs.sys")
def test_resolve_auto_darwin_fallback_when_no_accelerate():
"""On macOS, AUTO should fall back to QDLDL when Accelerate is missing."""
from unittest.mock import patch
from scs import _resolve_auto, _scs_direct

def fail_import(name):
raise ImportError(f"mocked: {name}")

with patch("scs.sys") as mock_sys:
mock_sys.platform = "darwin"
with patch("scs._load_module", side_effect=fail_import):
module = _resolve_auto()
assert module is _scs_direct


@pytest.mark.thread_unsafe(reason="patches module-level scs._load_module / scs.sys")
def test_resolve_auto_linux_fallback_when_no_mkl():
"""On Linux, AUTO should fall back to QDLDL when MKL is missing."""
Expand Down
Loading