scikit-sparse 0.5.0__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {scikit_sparse-0.5.0/src/scikit_sparse.egg-info → scikit_sparse-0.5.1}/PKG-INFO +2 -2
  2. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/pyproject.toml +2 -2
  3. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1/src/scikit_sparse.egg-info}/PKG-INFO +2 -2
  4. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/requires.txt +1 -1
  5. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/cholmod.pxd +5 -0
  6. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/cholmod.pyx +102 -69
  7. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/utils.py +9 -1
  8. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/LICENSE.txt +0 -0
  9. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/MANIFEST.in +0 -0
  10. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/README.rst +0 -0
  11. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/setup.cfg +0 -0
  12. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/setup.py +0 -0
  13. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/SOURCES.txt +0 -0
  14. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/dependency_links.txt +0 -0
  15. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/scikit_sparse.egg-info/top_level.txt +0 -0
  16. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/__init__.py +0 -0
  17. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/amd.pxd +0 -0
  18. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/amd.pyx +0 -0
  19. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/btf.pxd +0 -0
  20. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/btf.pyx +0 -0
  21. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/camd.pxd +0 -0
  22. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/camd.pyx +0 -0
  23. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/ccolamd.pxd +0 -0
  24. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/ccolamd.pyx +0 -0
  25. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/colamd.pxd +0 -0
  26. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/colamd.pyx +0 -0
  27. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/klu.pxd +0 -0
  28. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/klu.pyx +0 -0
  29. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/spqr.pxd +0 -0
  30. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/spqr.pyx +0 -0
  31. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/umfpack.pxd +0 -0
  32. {scikit_sparse-0.5.0 → scikit_sparse-0.5.1}/src/sksparse/umfpack.pyx +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-sparse
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library.
5
5
  Author-email: David Cournapeau <cournape@gmail.com>, Nathaniel Smith <njs@pobox.com>, Dag Sverre Seljebotn <dagss@student.matnat.uio.no>, Leon Barrett <lbarrett@climate.com>, Yuri <yuri@tsoft.com>, Antony Lee <anntzer.lee@gmail.com>, Alex Grigorievskiy <alex.grigorievskiy@gmail.com>, Joscha Reimer <jor@informatik.uni-kiel.de>, Justin Ellis <justin.ellis18@gmail.com>, Aaron Johnson <aaron9035@gmail.com>, Bernard Roesler <bernard.roesler@gmail.com>
6
6
  Maintainer-email: Bernard Roesler <bernard.roesler@gmail.com>
@@ -30,7 +30,7 @@ Provides-Extra: dev
30
30
  Requires-Dist: build; extra == "dev"
31
31
  Requires-Dist: pre-commit; extra == "dev"
32
32
  Requires-Dist: pytest; extra == "dev"
33
- Requires-Dist: ruff; extra == "dev"
33
+ Requires-Dist: ruff==0.14.3; extra == "dev"
34
34
  Requires-Dist: sphinx; extra == "dev"
35
35
  Requires-Dist: furo; extra == "dev"
36
36
  Requires-Dist: sphinx-copybutton; extra == "dev"
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "scikit-sparse"
8
- version = "0.5.0"
8
+ version = "0.5.1"
9
9
  description = "Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library."
10
10
  readme = "README.rst"
11
11
  requires-python = ">=3.10"
@@ -56,7 +56,7 @@ dev = [
56
56
  "build",
57
57
  "pre-commit",
58
58
  "pytest",
59
- "ruff",
59
+ "ruff==0.14.3",
60
60
  "sphinx",
61
61
  "furo",
62
62
  "sphinx-copybutton",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-sparse
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Scikit-sparse is a Python wrapper for the SuiteSparse sparse matrix library.
5
5
  Author-email: David Cournapeau <cournape@gmail.com>, Nathaniel Smith <njs@pobox.com>, Dag Sverre Seljebotn <dagss@student.matnat.uio.no>, Leon Barrett <lbarrett@climate.com>, Yuri <yuri@tsoft.com>, Antony Lee <anntzer.lee@gmail.com>, Alex Grigorievskiy <alex.grigorievskiy@gmail.com>, Joscha Reimer <jor@informatik.uni-kiel.de>, Justin Ellis <justin.ellis18@gmail.com>, Aaron Johnson <aaron9035@gmail.com>, Bernard Roesler <bernard.roesler@gmail.com>
6
6
  Maintainer-email: Bernard Roesler <bernard.roesler@gmail.com>
@@ -30,7 +30,7 @@ Provides-Extra: dev
30
30
  Requires-Dist: build; extra == "dev"
31
31
  Requires-Dist: pre-commit; extra == "dev"
32
32
  Requires-Dist: pytest; extra == "dev"
33
- Requires-Dist: ruff; extra == "dev"
33
+ Requires-Dist: ruff==0.14.3; extra == "dev"
34
34
  Requires-Dist: sphinx; extra == "dev"
35
35
  Requires-Dist: furo; extra == "dev"
36
36
  Requires-Dist: sphinx-copybutton; extra == "dev"
@@ -6,7 +6,7 @@ packaging
6
6
  build
7
7
  pre-commit
8
8
  pytest
9
- ruff
9
+ ruff==0.14.3
10
10
  sphinx
11
11
  furo
12
12
  sphinx-copybutton
@@ -205,6 +205,11 @@ cdef extern from "cholmod.h":
205
205
  int itype
206
206
  int xtype
207
207
  int dtype
208
+ size_t nsuper
209
+ size_t xsize
210
+ void *super
211
+ void *pi
212
+ void *px
208
213
 
209
214
  ctypedef struct cholmod_sparse:
210
215
  size_t nrow
@@ -112,6 +112,7 @@ import numpy as np
112
112
 
113
113
  from scipy.sparse import csc_array, diags_array, eye_array, issparse
114
114
  import warnings
115
+ import weakref
115
116
 
116
117
  from .utils import validate_csc_input
117
118
 
@@ -955,47 +956,6 @@ cdef cnp.ndarray _ndarray_copy_from_intptr(void* ptr, size_t N, bint use_int32):
955
956
  return p.copy() # return a copy in case ptr is freed
956
957
 
957
958
 
958
- cdef cnp.ndarray _ndarray_int_view_from_factor(
959
- void* ptr, size_t N, CholeskyFactor py_factor
960
- ):
961
- """Create a NumPy array from the an integer vector in a CHOLMOD factor.
962
-
963
- Parameters
964
- ----------
965
- ptr : void*
966
- A pointer to the C array, *e.g.* ``cholmod_factor.Perm``.
967
- N : size_t
968
- The size of the vector.
969
- py_factor : CholeskyFactor
970
- The CholeskyFactor object from which to extract the permutation.
971
-
972
- Returns
973
- -------
974
- p : ndarray
975
- The permutation vector as a NumPy array. This array is *read-only*,
976
- so attempts to modify it will raise an error.
977
- """
978
- cdef cholmod_factor *L = py_factor._factor
979
-
980
- if L is NULL:
981
- raise ValueError("The factor pointer is NULL.")
982
-
983
- if ptr is NULL:
984
- raise ValueError("The input pointer is NULL.")
985
-
986
- cdef int np_itypenum = _np_itypenum_from_cholmod(L.itype)
987
- p = cnp.PyArray_SimpleNewFromData(1, [N], np_itypenum, ptr)
988
-
989
- # NOTE need to increment reference count of base manually,
990
- # since the PyArray_SetBaseObject steals a reference.
991
- Py_INCREF(py_factor)
992
- if cnp.PyArray_SetBaseObject(p, py_factor) < 0:
993
- raise MemoryError("Failed to set base object for array.")
994
- cnp.PyArray_CLEARFLAGS(p, cnp.NPY_ARRAY_WRITEABLE) # set to be read-only
995
-
996
- return p
997
-
998
-
999
959
  # -----------------------------------------------------------------------------
1000
960
  # Utilities
1001
961
  # -----------------------------------------------------------------------------
@@ -1332,7 +1292,7 @@ cdef class CholeskyFactor:
1332
1292
  The ordering method used for the factorization. If an unknown ordering
1333
1293
  was used, returns the integer value.
1334
1294
  perm : *(N,)* :obj:`numpy.ndarray` of int
1335
- A read-only view of the permutation vector used for the factorization.
1295
+ A read-only copy of the permutation vector used for the factorization.
1336
1296
  factor : :obj:`~scipy.sparse.csc_array`
1337
1297
  A view of the the Cholesky factor in Compressed Sparse Column (CSC)
1338
1298
  format. If ``self.is_ll``, the returned matrix is lower triangular.
@@ -1407,6 +1367,7 @@ cdef class CholeskyFactor:
1407
1367
  # Cached factors
1408
1368
  cnp.ndarray _perm
1409
1369
  cnp.ndarray _colcount
1370
+ object _pattern
1410
1371
  object _L
1411
1372
  object _R
1412
1373
  object _D
@@ -1508,6 +1469,10 @@ cdef class CholeskyFactor:
1508
1469
  cdef int minor = -1 if self._factor is NULL else self._factor.minor
1509
1470
  _handle_errors(self._cm.status, minor)
1510
1471
 
1472
+ # The supernodal algorithm requires A to have the analyzed pattern
1473
+ if self._factor.is_super:
1474
+ self._pattern = (A.shape, A.indptr.copy(), A.indices.copy())
1475
+
1511
1476
  def __dealloc__(self):
1512
1477
  """Deallocate memory used by the CholeskyFactor."""
1513
1478
  if self._use_int32:
@@ -1522,6 +1487,23 @@ cdef class CholeskyFactor:
1522
1487
  if not self.is_numeric:
1523
1488
  raise CholmodError("Factor is symbolic. Call `factorize` before updating.")
1524
1489
 
1490
+ cdef int _to_simplicial(self) except -1:
1491
+ """Convert the factor to simplicial format, keeping its values."""
1492
+ cdef cholmod_factor *L = self._factor
1493
+ if self._use_int32:
1494
+ cholmod_change_factor(L.xtype, L.is_ll, False, True, True, L, self._cm)
1495
+ else:
1496
+ cholmod_l_change_factor(L.xtype, L.is_ll, False, True, True, L, self._cm)
1497
+ return _handle_errors(self._cm.status)
1498
+
1499
+ cdef bint _has_pattern(self, object A) except -1:
1500
+ """Check whether A has the analyzed (supernodal) sparsity pattern."""
1501
+ return self._pattern is not None and (
1502
+ A.shape == self._pattern[0]
1503
+ and np.array_equal(A.indptr, self._pattern[1])
1504
+ and np.array_equal(A.indices, self._pattern[2])
1505
+ )
1506
+
1525
1507
  def _clear_cache(self):
1526
1508
  """Clear cached properties."""
1527
1509
  self._factor_view = None
@@ -1590,9 +1572,10 @@ cdef class CholeskyFactor:
1590
1572
  @property
1591
1573
  def colcount(self):
1592
1574
  if self._colcount is None:
1593
- self._colcount = _ndarray_int_view_from_factor(
1594
- self._factor.ColCount, self._factor.n, self
1575
+ self._colcount = _ndarray_copy_from_intptr(
1576
+ self._factor.ColCount, self._factor.n, self._use_int32
1595
1577
  )
1578
+ self._colcount.flags.writeable = False
1596
1579
  return self._colcount
1597
1580
 
1598
1581
  @property
@@ -1607,14 +1590,21 @@ cdef class CholeskyFactor:
1607
1590
  @property
1608
1591
  def perm(self):
1609
1592
  if self._perm is None:
1610
- self._perm = _ndarray_int_view_from_factor(self._factor.Perm, self._factor.n, self)
1593
+ self._perm = _ndarray_copy_from_intptr(
1594
+ self._factor.Perm, self._factor.n, self._use_int32
1595
+ )
1596
+ self._perm.flags.writeable = False
1611
1597
  return self._perm
1612
1598
 
1613
1599
  @property
1614
1600
  def factor(self):
1615
- if self._factor_view is None:
1616
- self._factor_view = _csc_view_from_cholmod_factor(self)
1617
- return self._factor_view
1601
+ # NOTE cache a weak reference, since the view has self as its base,
1602
+ # and a reference cycle through a NumPy array is never garbage collected.
1603
+ Lv = None if self._factor_view is None else self._factor_view()
1604
+ if Lv is None:
1605
+ Lv = _csc_view_from_cholmod_factor(self)
1606
+ self._factor_view = weakref.ref(Lv)
1607
+ return Lv
1618
1608
 
1619
1609
  @property
1620
1610
  def L(self):
@@ -1687,6 +1677,7 @@ cdef class CholeskyFactor:
1687
1677
  cf._stype = self._stype
1688
1678
  cf.sym_kind = self.sym_kind
1689
1679
  cf.rcond = self.rcond
1680
+ cf._pattern = self._pattern
1690
1681
 
1691
1682
  return cf
1692
1683
 
@@ -1722,7 +1713,7 @@ cdef class CholeskyFactor:
1722
1713
  self._clear_cache()
1723
1714
 
1724
1715
  cdef int to_ll = (kind == "LL")
1725
- cdef int to_super = self._factor.is_super
1716
+ cdef int to_super = self._factor.is_super and to_ll
1726
1717
  cdef int to_packed = True
1727
1718
  cdef int to_monotonic = self._factor.is_monotonic
1728
1719
 
@@ -1784,16 +1775,20 @@ cdef class CholeskyFactor:
1784
1775
  if lower is None:
1785
1776
  lower = self.is_lower
1786
1777
 
1778
+ # Convert a copy of the factor if needed, so that this one is unchanged
1779
+ same_kind = self.is_ll == (kind == "LL")
1780
+ cf = self if same_kind and not self.is_super else self.copy()
1781
+
1787
1782
  # Drop explicit zeros from returned copies
1788
1783
  if kind == "LL":
1789
- L = _csc_view_from_cholmod_factor(self, ldl=False).copy()
1784
+ L = _csc_view_from_cholmod_factor(cf, ldl=False).copy()
1790
1785
  L.eliminate_zeros()
1791
1786
  if not lower:
1792
1787
  L = L.T.conj()
1793
1788
  return L
1794
1789
  else:
1795
1790
  # Extract L and D from combined LD factor
1796
- L = _csc_view_from_cholmod_factor(self, ldl=True).copy()
1791
+ L = _csc_view_from_cholmod_factor(cf, ldl=True).copy()
1797
1792
  D = diags_array(L.diagonal())
1798
1793
  L.setdiag(1.0)
1799
1794
  L.eliminate_zeros()
@@ -1887,7 +1882,17 @@ cdef class CholeskyFactor:
1887
1882
  """
1888
1883
  assert self._factor is not NULL, "The factor has not been initialized."
1889
1884
 
1890
- A, _, _ = validate_csc_input(A, ensure_double=False)
1885
+ # Skip validation of a matrix with exactly the analyzed pattern, which
1886
+ # is canonical, as is common when refactorizing
1887
+ cdef bint same_pattern = (
1888
+ issparse(A) and A.format == "csc" and A.dtype.kind in "fc"
1889
+ and A.indptr.dtype == A.indices.dtype == self.itype
1890
+ and A.data.shape == A.indices.shape and A.data.flags.c_contiguous
1891
+ and self._has_pattern(A)
1892
+ )
1893
+ if not same_pattern:
1894
+ A, _, _ = validate_csc_input(A, ensure_double=False, itype=self.itype)
1895
+ same_pattern = self._has_pattern(A)
1891
1896
 
1892
1897
  if ldl is None:
1893
1898
  if self.is_numeric:
@@ -1898,12 +1903,26 @@ cdef class CholeskyFactor:
1898
1903
  if not isinstance(ldl, bool):
1899
1904
  raise ValueError("ldl must be a boolean value.")
1900
1905
 
1906
+ # Check A as CHOLMOD does, since CHOLMOD may change the factor (e.g.,
1907
+ # is_ll) before it rejects A, and the factor is converted below
1908
+ n = A.shape[1] if self.sym_kind == "col" else A.shape[0]
1909
+ if n != self.N or (self._stype != 0 and A.shape[0] != A.shape[1]) or (
1910
+ self.is_numeric and A.dtype != self.dtype
1911
+ ):
1912
+ raise CholmodInvalidInputError("A does not match the factor.")
1913
+
1901
1914
  # Clear cached properties
1902
1915
  self._clear_cache()
1903
1916
 
1917
+ # A supernodal factor is LL.T only, and silently gives a wrong result
1918
+ # for a matrix outside of the analyzed pattern, so use the simplicial
1919
+ # algorithm instead.
1920
+ if self._factor.is_super and ((ldl and self.is_numeric) or not same_pattern):
1921
+ self._to_simplicial()
1922
+
1904
1923
  # See CHOLMOD/MATLAB/ldlchol.c and/or lchol.c for details
1905
1924
  self._cm.final_asis = False
1906
- self._cm.final_super = False
1925
+ self._cm.final_super = not ldl # keep a supernodal LL.T factor
1907
1926
  self._cm.final_ll = not ldl # LL.T for Cholesky, LDL.T for LDL
1908
1927
  self._cm.final_pack = True
1909
1928
  self._cm.final_monotonic = True
@@ -2109,7 +2128,7 @@ cdef class CholeskyFactor:
2109
2128
 
2110
2129
  cdef int stype = 0
2111
2130
 
2112
- b, _, _ = validate_csc_input(b, ensure_double=False)
2131
+ b, _, _ = validate_csc_input(b, ensure_double=False, itype=self.itype)
2113
2132
 
2114
2133
  _cholmod_sparse_from_csc(
2115
2134
  b.shape, b.indptr, b.indices, b.data, stype, <uintptr_t>&Bspmatrix
@@ -2203,7 +2222,7 @@ cdef class CholeskyFactor:
2203
2222
  C = C.reshape((-1, 1)).tocsc() # (N, 1)
2204
2223
 
2205
2224
  cdef int stype = 0 # use all of C
2206
- C, _, _ = validate_csc_input(C, ensure_double=False)
2225
+ C, _, _ = validate_csc_input(C, ensure_double=False, itype=self.itype)
2207
2226
 
2208
2227
  cdef cholmod_sparse Cmatrix
2209
2228
  cdef cholmod_sparse* Cc = &Cmatrix
@@ -2256,6 +2275,7 @@ cdef class CholeskyFactor:
2256
2275
  cholmod_l_free_sparse(&C_perm, self._cm)
2257
2276
 
2258
2277
  if not ok:
2278
+ _handle_errors(self._cm.status)
2259
2279
  raise CholmodError("Update or downdate failed.")
2260
2280
 
2261
2281
  return self
@@ -2313,7 +2333,7 @@ cdef class CholeskyFactor:
2313
2333
  if C.ndim == 1:
2314
2334
  C = C.reshape((-1, 1)).tocsc() # (N, 1)
2315
2335
 
2316
- C, _, _ = validate_csc_input(C, ensure_double=False)
2336
+ C, _, _ = validate_csc_input(C, ensure_double=False, itype=self.itype)
2317
2337
  _cholmod_sparse_from_csc(
2318
2338
  C.shape, C.indptr, C.indices, C.data, stype, <uintptr_t>&Cmatrix
2319
2339
  )
@@ -2327,6 +2347,7 @@ cdef class CholeskyFactor:
2327
2347
  ok = cholmod_l_rowadd(k, Cc, self._factor, self._cm)
2328
2348
 
2329
2349
  if not ok:
2350
+ _handle_errors(self._cm.status)
2330
2351
  raise CholmodError("cholmod_rowadd failed.")
2331
2352
 
2332
2353
  return self
@@ -2368,6 +2389,7 @@ cdef class CholeskyFactor:
2368
2389
  ok = cholmod_l_rowdel(k, NULL, self._factor, self._cm)
2369
2390
 
2370
2391
  if not ok:
2392
+ _handle_errors(self._cm.status)
2371
2393
  raise CholmodError("cholmod_rowdel failed.")
2372
2394
 
2373
2395
  return self
@@ -2416,21 +2438,16 @@ cdef class CholeskyFactor:
2416
2438
  """
2417
2439
  self._require_factorized()
2418
2440
 
2419
- cdef bint A_use_int32
2420
2441
  # TODO support non-square matrices with sym_kind='row'
2421
- A, A_use_int32, _ = validate_csc_input(A, require_square=True, ensure_double=False)
2442
+ A, _, _ = validate_csc_input(
2443
+ A, require_square=True, ensure_double=False, itype=self.itype
2444
+ )
2422
2445
 
2423
2446
  if A.shape[0] != self.N:
2424
2447
  raise ValueError(
2425
2448
  "Input matrix A must have the same number of rows as L."
2426
2449
  )
2427
2450
 
2428
- if self._use_int32 and not A_use_int32:
2429
- raise ValueError(
2430
- "A and factor must have the same integer type. "
2431
- f"Got {A.indptr.dtype=}, but {self._use_int32=}."
2432
- )
2433
-
2434
2451
  # Special Cases
2435
2452
  if self.N == 0:
2436
2453
  return self
@@ -2441,6 +2458,8 @@ cdef class CholeskyFactor:
2441
2458
  # Clear cached properties
2442
2459
  self._clear_cache()
2443
2460
 
2461
+ self._to_simplicial() # CHOLMOD cannot resymbol a supernodal factor
2462
+
2444
2463
  # Get sparse *pattern*
2445
2464
  cdef cholmod_sparse Amatrix
2446
2465
  cdef cholmod_sparse* Ac = &Amatrix
@@ -2466,6 +2485,7 @@ cdef class CholeskyFactor:
2466
2485
  else:
2467
2486
  cholmod_l_resymbol(Ac, NULL, 0, True, self._factor, self._cm)
2468
2487
 
2488
+ _handle_errors(self._cm.status)
2469
2489
  return self
2470
2490
 
2471
2491
  def logdet(self):
@@ -2502,12 +2522,25 @@ cdef class CholeskyFactor:
2502
2522
  .. versionadded:: 0.2
2503
2523
  """
2504
2524
  self._require_factorized()
2505
- if self.is_ll:
2506
- L = self.get_factor()
2507
- return 2 * np.sum(np.log(L.diagonal()))
2525
+ cdef cholmod_factor *L = self._factor
2526
+ cdef int it = _np_itypenum_from_cholmod(L.itype)
2527
+ cdef int dt = _np_dtypenum_from_cholmod(L.xtype, L.dtype)
2528
+ # The diagonal of L (or D) is the first entry of each column of
2529
+ # a simplicial factor. A supernodal factor stores each supernode as
2530
+ # a dense column-major block with nsrow rows. See cholmod_rcond.c.
2531
+ if L.is_super:
2532
+ S = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.super)
2533
+ pi = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.pi)
2534
+ px = cnp.PyArray_SimpleNewFromData(1, [L.nsuper + 1], it, L.px)
2535
+ x = cnp.PyArray_SimpleNewFromData(1, [L.xsize], dt, L.x)
2536
+ s = np.repeat(np.arange(L.nsuper), np.diff(S))
2537
+ j = np.arange(L.n) - S[s]
2538
+ d = x[px[s] + j * (np.diff(pi)[s] + 1)]
2508
2539
  else:
2509
- _, D = self.get_factor()
2510
- return np.sum(np.log(D.diagonal()))
2540
+ Lp = cnp.PyArray_SimpleNewFromData(1, [L.n + 1], it, L.p)
2541
+ x = cnp.PyArray_SimpleNewFromData(1, [L.nzmax], dt, L.x)
2542
+ d = x[Lp[:-1]]
2543
+ return (2 if self.is_ll else 1) * np.sum(np.log(d))
2511
2544
 
2512
2545
  def slogdet(self):
2513
2546
  """Compute the sign and (natural) log-determinant of the matrix from
@@ -20,7 +20,7 @@ from scipy.sparse import SparseEfficiencyWarning, csc_array, issparse
20
20
  _HAS_SCIPY_SORT_BUG = version.parse(scipy_version) < version.parse("1.17.0")
21
21
 
22
22
 
23
- def validate_csc_input(A, require_square=False, ensure_double=True):
23
+ def validate_csc_input(A, require_square=False, ensure_double=True, itype=None):
24
24
  """Validate and convert input matrix to CSC format.
25
25
 
26
26
  Integer and boolean data types are converted to float32 by default.
@@ -39,6 +39,8 @@ def validate_csc_input(A, require_square=False, ensure_double=True):
39
39
  Otherwise, it will retain its original floating-point precision
40
40
  (float32 or complex64), or the minimum precision required to convert
41
41
  integer or boolean types.
42
+ itype : dtype, optional
43
+ If given, the index arrays are converted to this integer type.
42
44
 
43
45
  Returns
44
46
  -------
@@ -114,6 +116,12 @@ def validate_csc_input(A, require_square=False, ensure_double=True):
114
116
  if not (A.has_sorted_indices and A.has_canonical_format):
115
117
  raise ValueError("Failed to convert input to canonical CSC format.")
116
118
 
119
+ # NOTE set the index arrays after construction, since the constructor
120
+ # may choose a different index type.
121
+ if itype is not None and not (A.indptr.dtype == A.indices.dtype == itype):
122
+ A = csc_array((A.data, A.indices, A.indptr), shape=A.shape)
123
+ A.indptr, A.indices = A.indptr.astype(itype), A.indices.astype(itype)
124
+
117
125
  # Choose index width: int32 or int64
118
126
  use_int32 = A.indptr.dtype == np.int32 and A.indices.dtype == np.int32
119
127
  out_itype = np.dtype(np.int32 if use_int32 else np.int64)
File without changes
File without changes
File without changes
File without changes
File without changes