scipy 1.15.2__cp312-cp312-win_amd64.whl → 1.15.3__cp312-cp312-win_amd64.whl
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.
- scipy/__config__.py +6 -6
- scipy/__init__.py +3 -3
- scipy/_lib/_array_api.py +11 -0
- scipy/_lib/_ccallback_c.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_ccallback_c.cp312-win_amd64.pyd +0 -0
- scipy/_lib/_fpumode.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_fpumode.cp312-win_amd64.pyd +0 -0
- scipy/_lib/_test_ccallback.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_test_ccallback.cp312-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_call.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_call.cp312-win_amd64.pyd +0 -0
- scipy/_lib/_test_deprecation_def.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_test_deprecation_def.cp312-win_amd64.pyd +0 -0
- scipy/_lib/_uarray/_uarray.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/_uarray/_uarray.cp312-win_amd64.pyd +0 -0
- scipy/_lib/messagestream.cp312-win_amd64.dll.a +0 -0
- scipy/_lib/messagestream.cp312-win_amd64.pyd +0 -0
- scipy/_lib/tests/test_array_api.py +5 -1
- scipy/cluster/_hierarchy.cp312-win_amd64.dll.a +0 -0
- scipy/cluster/_hierarchy.cp312-win_amd64.pyd +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp312-win_amd64.dll.a +0 -0
- scipy/cluster/_optimal_leaf_ordering.cp312-win_amd64.pyd +0 -0
- scipy/cluster/_vq.cp312-win_amd64.dll.a +0 -0
- scipy/cluster/_vq.cp312-win_amd64.pyd +0 -0
- scipy/fft/_pocketfft/pypocketfft.cp312-win_amd64.dll.a +0 -0
- scipy/fft/_pocketfft/pypocketfft.cp312-win_amd64.pyd +0 -0
- scipy/fftpack/convolve.cp312-win_amd64.dll.a +0 -0
- scipy/fftpack/convolve.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_dop.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_dop.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_ivp/common.py +3 -3
- scipy/integrate/_ivp/ivp.py +9 -2
- scipy/integrate/_ivp/tests/test_ivp.py +19 -0
- scipy/integrate/_lsoda.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_lsoda.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_odepack.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_odepack.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_quadpack.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_quadpack.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_tanhsinh.py +14 -12
- scipy/integrate/_test_multivariate.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_test_multivariate.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_test_odeint_banded.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_test_odeint_banded.cp312-win_amd64.pyd +0 -0
- scipy/integrate/_vode.cp312-win_amd64.dll.a +0 -0
- scipy/integrate/_vode.cp312-win_amd64.pyd +0 -0
- scipy/integrate/tests/test_tanhsinh.py +10 -0
- scipy/interpolate/_bspl.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_bspl.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_dfitpack.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_dfitpack.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_dierckx.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_dierckx.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_fitpack.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_fitpack.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_interpnd.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_interpnd.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_ppoly.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_ppoly.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_rbfinterp_pythran.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_rbfinterp_pythran.cp312-win_amd64.pyd +0 -0
- scipy/interpolate/_rgi_cython.cp312-win_amd64.dll.a +0 -0
- scipy/interpolate/_rgi_cython.cp312-win_amd64.pyd +0 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp312-win_amd64.dll.a +0 -0
- scipy/io/_fast_matrix_market/_fmm_core.cp312-win_amd64.pyd +0 -0
- scipy/io/_test_fortran.cp312-win_amd64.dll.a +0 -0
- scipy/io/_test_fortran.cp312-win_amd64.pyd +0 -0
- scipy/io/matlab/_mio5_utils.cp312-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio5_utils.cp312-win_amd64.pyd +0 -0
- scipy/io/matlab/_mio_utils.cp312-win_amd64.dll.a +0 -0
- scipy/io/matlab/_mio_utils.cp312-win_amd64.pyd +0 -0
- scipy/io/matlab/_streams.cp312-win_amd64.dll.a +0 -0
- scipy/io/matlab/_streams.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_cythonized_array_utils.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_cythonized_array_utils.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_interpolative.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_interpolative.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_lu_cython.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_lu_cython.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_decomp_update.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_decomp_update.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_fblas.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_fblas.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_flapack.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_flapack.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_linalg_pythran.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_linalg_pythran.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_expm.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_expm.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_matfuncs_sqrtm_triu.cp312-win_amd64.pyd +0 -0
- scipy/linalg/_solve_toeplitz.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/_solve_toeplitz.cp312-win_amd64.pyd +0 -0
- scipy/linalg/cython_blas.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/cython_blas.cp312-win_amd64.pyd +0 -0
- scipy/linalg/cython_lapack.cp312-win_amd64.dll.a +0 -0
- scipy/linalg/cython_lapack.cp312-win_amd64.pyd +0 -0
- scipy/linalg/tests/test_interpolative.py +17 -0
- scipy/ndimage/_ctest.cp312-win_amd64.dll.a +0 -0
- scipy/ndimage/_ctest.cp312-win_amd64.pyd +0 -0
- scipy/ndimage/_cytest.cp312-win_amd64.dll.a +0 -0
- scipy/ndimage/_cytest.cp312-win_amd64.pyd +0 -0
- scipy/ndimage/_nd_image.cp312-win_amd64.dll.a +0 -0
- scipy/ndimage/_nd_image.cp312-win_amd64.pyd +0 -0
- scipy/ndimage/_ndimage_api.py +2 -1
- scipy/ndimage/_ni_label.cp312-win_amd64.dll.a +0 -0
- scipy/ndimage/_ni_label.cp312-win_amd64.pyd +0 -0
- scipy/ndimage/_rank_filter_1d.cp312-win_amd64.dll.a +0 -0
- scipy/ndimage/_rank_filter_1d.cp312-win_amd64.pyd +0 -0
- scipy/ndimage/tests/test_filters.py +14 -0
- scipy/odr/__odrpack.cp312-win_amd64.dll.a +0 -0
- scipy/odr/__odrpack.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_bglu_dense.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_bglu_dense.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_bracket.py +35 -8
- scipy/optimize/_cobyla.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_cobyla.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_cython_nnls.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_cython_nnls.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_direct.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_direct.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_group_columns.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_group_columns.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_core.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_core.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_highs_options.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_highspy/_highs_options.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_highspy/_highs_wrapper.py +6 -4
- scipy/optimize/_lbfgsb.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_lbfgsb.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_linprog_highs.py +9 -9
- scipy/optimize/_linprog_util.py +4 -3
- scipy/optimize/_lsap.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_lsap.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_lsq/givens_elimination.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_lsq/givens_elimination.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_minpack.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_minpack.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_moduleTNC.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_moduleTNC.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_pava_pybind.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_pava_pybind.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_slsqp.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_slsqp.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_trlib/_trlib.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_trlib/_trlib.cp312-win_amd64.pyd +0 -0
- scipy/optimize/_zeros.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/_zeros.cp312-win_amd64.pyd +0 -0
- scipy/optimize/cython_optimize/_zeros.cp312-win_amd64.dll.a +0 -0
- scipy/optimize/cython_optimize/_zeros.cp312-win_amd64.pyd +0 -0
- scipy/optimize/tests/test_bracket.py +35 -0
- scipy/signal/_max_len_seq_inner.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_max_len_seq_inner.cp312-win_amd64.pyd +0 -0
- scipy/signal/_peak_finding_utils.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_peak_finding_utils.cp312-win_amd64.pyd +0 -0
- scipy/signal/_short_time_fft.py +34 -6
- scipy/signal/_signaltools.py +4 -1
- scipy/signal/_sigtools.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_sigtools.cp312-win_amd64.pyd +0 -0
- scipy/signal/_sosfilt.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_sosfilt.cp312-win_amd64.pyd +0 -0
- scipy/signal/_spline.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_spline.cp312-win_amd64.pyd +0 -0
- scipy/signal/_upfirdn_apply.cp312-win_amd64.dll.a +0 -0
- scipy/signal/_upfirdn_apply.cp312-win_amd64.pyd +0 -0
- scipy/signal/tests/_scipy_spectral_test_shim.py +3 -11
- scipy/signal/tests/test_short_time_fft.py +10 -2
- scipy/signal/tests/test_signaltools.py +5 -0
- scipy/sparse/_base.py +2 -15
- scipy/sparse/_compressed.py +0 -3
- scipy/sparse/_csparsetools.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/_csparsetools.cp312-win_amd64.pyd +0 -0
- scipy/sparse/_dia.py +0 -3
- scipy/sparse/_sparsetools.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/_sparsetools.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_flow.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_flow.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_matching.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_matching.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_reordering.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_reordering.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_shortest_path.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_shortest_path.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_tools.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_tools.cp312-win_amd64.pyd +0 -0
- scipy/sparse/csgraph/_traversal.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/csgraph/_traversal.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_dsolve/_superlu.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_eigen/arpack/_arpack.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_eigen/arpack/arpack.py +5 -3
- scipy/sparse/linalg/_expm_multiply.py +8 -3
- scipy/sparse/linalg/_interface.py +12 -8
- scipy/sparse/linalg/_isolve/_gcrotmk.py +2 -1
- scipy/sparse/linalg/_propack/_cpropack.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_cpropack.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_spropack.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp312-win_amd64.dll.a +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cp312-win_amd64.pyd +0 -0
- scipy/sparse/linalg/tests/test_expm_multiply.py +10 -0
- scipy/sparse/linalg/tests/test_interface.py +35 -0
- scipy/sparse/linalg/tests/test_pydata_sparse.py +4 -0
- scipy/sparse/tests/test_base.py +12 -0
- scipy/sparse/tests/test_common1d.py +11 -6
- scipy/spatial/_ckdtree.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_ckdtree.cp312-win_amd64.pyd +0 -0
- scipy/spatial/_distance_pybind.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_pybind.cp312-win_amd64.pyd +0 -0
- scipy/spatial/_distance_wrap.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_distance_wrap.cp312-win_amd64.pyd +0 -0
- scipy/spatial/_hausdorff.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_hausdorff.cp312-win_amd64.pyd +0 -0
- scipy/spatial/_qhull.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_qhull.cp312-win_amd64.pyd +0 -0
- scipy/spatial/_voronoi.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/_voronoi.cp312-win_amd64.pyd +0 -0
- scipy/spatial/tests/test_qhull.py +99 -0
- scipy/spatial/transform/_rotation.cp312-win_amd64.dll.a +0 -0
- scipy/spatial/transform/_rotation.cp312-win_amd64.pyd +0 -0
- scipy/spatial/transform/tests/test_rotation.py +181 -10
- scipy/special/_comb.cp312-win_amd64.dll.a +0 -0
- scipy/special/_comb.cp312-win_amd64.pyd +0 -0
- scipy/special/_ellip_harm_2.cp312-win_amd64.dll.a +0 -0
- scipy/special/_ellip_harm_2.cp312-win_amd64.pyd +0 -0
- scipy/special/_gufuncs.cp312-win_amd64.dll.a +0 -0
- scipy/special/_gufuncs.cp312-win_amd64.pyd +0 -0
- scipy/special/_logsumexp.py +21 -16
- scipy/special/_specfun.cp312-win_amd64.dll.a +0 -0
- scipy/special/_specfun.cp312-win_amd64.pyd +0 -0
- scipy/special/_special_ufuncs.cp312-win_amd64.dll.a +0 -0
- scipy/special/_special_ufuncs.cp312-win_amd64.pyd +0 -0
- scipy/special/_test_internal.cp312-win_amd64.dll.a +0 -0
- scipy/special/_test_internal.cp312-win_amd64.pyd +0 -0
- scipy/special/_ufuncs.cp312-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs.cp312-win_amd64.pyd +0 -0
- scipy/special/_ufuncs_cxx.cp312-win_amd64.dll.a +0 -0
- scipy/special/_ufuncs_cxx.cp312-win_amd64.pyd +0 -0
- scipy/special/cython_special.cp312-win_amd64.dll.a +0 -0
- scipy/special/cython_special.cp312-win_amd64.pyd +0 -0
- scipy/special/libsf_error_state.dll +0 -0
- scipy/special/libsf_error_state.dll.a +0 -0
- scipy/special/tests/test_hyp2f1.py +21 -0
- scipy/special/tests/test_logsumexp.py +14 -0
- scipy/special/xsf/hyp2f1.h +3 -3
- scipy/stats/_ansari_swilk_statistics.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_ansari_swilk_statistics.cp312-win_amd64.pyd +0 -0
- scipy/stats/_biasedurn.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_biasedurn.cp312-win_amd64.pyd +0 -0
- scipy/stats/_continuous_distns.py +25 -15
- scipy/stats/_levy_stable/levyst.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_levy_stable/levyst.cp312-win_amd64.pyd +0 -0
- scipy/stats/_mvn.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_mvn.cp312-win_amd64.pyd +0 -0
- scipy/stats/_qmc_cy.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_qmc_cy.cp312-win_amd64.pyd +0 -0
- scipy/stats/_rcont/rcont.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_rcont/rcont.cp312-win_amd64.pyd +0 -0
- scipy/stats/_sobol.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_sobol.cp312-win_amd64.pyd +0 -0
- scipy/stats/_stats.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_stats.cp312-win_amd64.pyd +0 -0
- scipy/stats/_stats_pythran.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_stats_pythran.cp312-win_amd64.pyd +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp312-win_amd64.dll.a +0 -0
- scipy/stats/_unuran/unuran_wrapper.cp312-win_amd64.pyd +0 -0
- scipy/stats/tests/test_distributions.py +22 -0
- scipy/version.py +2 -2
- scipy-1.15.3.dist-info/DELVEWHEEL +2 -0
- {scipy-1.15.2.dist-info → scipy-1.15.3.dist-info}/METADATA +2 -2
- {scipy-1.15.2.dist-info → scipy-1.15.3.dist-info}/RECORD +279 -279
- scipy-1.15.2.dist-info/DELVEWHEEL +0 -2
- /scipy-1.15.2-cp312-cp312-win_amd64.whl → /scipy-1.15.3-cp312-cp312-win_amd64.whl +0 -0
- {scipy-1.15.2.dist-info → scipy-1.15.3.dist-info}/LICENSE.txt +0 -0
- {scipy-1.15.2.dist-info → scipy-1.15.3.dist-info}/WHEEL +0 -0
@@ -115,7 +115,7 @@ def expm_multiply(A, B, start=None, stop=None, num=None,
|
|
115
115
|
----------
|
116
116
|
A : transposable linear operator
|
117
117
|
The operator whose exponential is of interest.
|
118
|
-
B : ndarray
|
118
|
+
B : ndarray, sparse array
|
119
119
|
The matrix or vector to be multiplied by the matrix exponential of A.
|
120
120
|
start : scalar, optional
|
121
121
|
The starting time point of the sequence.
|
@@ -443,7 +443,7 @@ class LazyOperatorNormInfo:
|
|
443
443
|
|
444
444
|
def d(self, p):
|
445
445
|
"""
|
446
|
-
Lazily estimate :math:`d_p(A) ~= || A^p ||^(1/p)`
|
446
|
+
Lazily estimate :math:`d_p(A) ~= || A^p ||^(1/p)`
|
447
447
|
where :math:`||.||` is the 1-norm.
|
448
448
|
"""
|
449
449
|
if p not in self._d:
|
@@ -702,7 +702,12 @@ def _expm_multiply_interval(A, B, start=None, stop=None, num=None,
|
|
702
702
|
m_star, s = _fragment_3_1(norm_info, n0, tol, ell=ell)
|
703
703
|
|
704
704
|
# Compute the expm action up to the initial time point.
|
705
|
-
|
705
|
+
action_t0 = _expm_multiply_simple_core(A, B, t_0, mu, m_star, s)
|
706
|
+
if scipy.sparse.issparse(action_t0):
|
707
|
+
action_t0 = action_t0.toarray()
|
708
|
+
elif is_pydata_spmatrix(action_t0):
|
709
|
+
action_t0 = action_t0.todense()
|
710
|
+
X[0] = action_t0
|
706
711
|
|
707
712
|
# Compute the expm action at the rest of the time points.
|
708
713
|
if q <= s:
|
@@ -322,6 +322,10 @@ class LinearOperator:
|
|
322
322
|
"""Default implementation of _rmatvec; defers to adjoint."""
|
323
323
|
if type(self)._adjoint == LinearOperator._adjoint:
|
324
324
|
# _adjoint not overridden, prevent infinite recursion
|
325
|
+
if (hasattr(self, "_rmatmat")
|
326
|
+
and type(self)._rmatmat != LinearOperator._rmatmat):
|
327
|
+
# Try to use _rmatmat as a fallback
|
328
|
+
return self._rmatmat(x.reshape(-1, 1)).reshape(-1)
|
325
329
|
raise NotImplementedError
|
326
330
|
else:
|
327
331
|
return self.H.matvec(x)
|
@@ -822,22 +826,22 @@ class MatrixLinearOperator(LinearOperator):
|
|
822
826
|
|
823
827
|
def _adjoint(self):
|
824
828
|
if self.__adj is None:
|
825
|
-
self.__adj = _AdjointMatrixOperator(self)
|
829
|
+
self.__adj = _AdjointMatrixOperator(self.A)
|
826
830
|
return self.__adj
|
827
831
|
|
832
|
+
|
828
833
|
class _AdjointMatrixOperator(MatrixLinearOperator):
|
829
|
-
def __init__(self,
|
830
|
-
self.A =
|
831
|
-
self.
|
832
|
-
self.
|
833
|
-
self.shape = adjoint.shape[1], adjoint.shape[0]
|
834
|
+
def __init__(self, adjoint_array):
|
835
|
+
self.A = adjoint_array.T.conj()
|
836
|
+
self.args = (adjoint_array,)
|
837
|
+
self.shape = adjoint_array.shape[1], adjoint_array.shape[0]
|
834
838
|
|
835
839
|
@property
|
836
840
|
def dtype(self):
|
837
|
-
return self.
|
841
|
+
return self.args[0].dtype
|
838
842
|
|
839
843
|
def _adjoint(self):
|
840
|
-
return self.
|
844
|
+
return MatrixLinearOperator(self.args[0])
|
841
845
|
|
842
846
|
|
843
847
|
class IdentityOperator(LinearOperator):
|
@@ -433,7 +433,8 @@ def gcrotmk(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=1000, M=None, callback
|
|
433
433
|
ux = axpy(u, ux, ux.shape[0], -byc) # ux -= u*byc
|
434
434
|
|
435
435
|
# cx := V H y
|
436
|
-
|
436
|
+
with np.errstate(invalid="ignore"):
|
437
|
+
hy = Q.dot(R.dot(y))
|
437
438
|
cx = vs[0] * hy[0]
|
438
439
|
for v, hyc in zip(vs[1:], hy[1:]):
|
439
440
|
cx = axpy(v, cx, cx.shape[0], hyc) # cx += v*hyc
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -7,6 +7,7 @@ import pytest
|
|
7
7
|
from numpy.testing import (assert_allclose, assert_, assert_equal,
|
8
8
|
suppress_warnings)
|
9
9
|
from scipy.sparse import SparseEfficiencyWarning
|
10
|
+
import scipy.sparse
|
10
11
|
from scipy.sparse.linalg import aslinearoperator
|
11
12
|
import scipy.linalg
|
12
13
|
from scipy.sparse.linalg import expm as sp_expm
|
@@ -260,19 +261,28 @@ class TestExpmActionInterval:
|
|
260
261
|
A = scipy.sparse.diags_array(np.arange(5),format='csr', dtype=int)
|
261
262
|
B = np.ones(5, dtype=int)
|
262
263
|
Aexpm = scipy.sparse.diags_array(np.exp(np.arange(5)),format='csr')
|
264
|
+
BI = np.identity(5, dtype=int)
|
265
|
+
BI_sparse = scipy.sparse.csr_array(BI)
|
263
266
|
assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B))
|
267
|
+
assert_allclose(np.diag(expm_multiply(A, BI_sparse, 0, 1)[-1]), Aexpm.dot(B))
|
264
268
|
|
265
269
|
# Test A complex, B int
|
266
270
|
A = scipy.sparse.diags_array(-1j*np.arange(5),format='csr', dtype=complex)
|
267
271
|
B = np.ones(5, dtype=int)
|
268
272
|
Aexpm = scipy.sparse.diags_array(np.exp(-1j*np.arange(5)),format='csr')
|
269
273
|
assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B))
|
274
|
+
assert_allclose(np.diag(expm_multiply(A, BI_sparse, 0, 1)[-1]), Aexpm.dot(B))
|
270
275
|
|
271
276
|
# Test A int, B complex
|
272
277
|
A = scipy.sparse.diags_array(np.arange(5),format='csr', dtype=int)
|
273
278
|
B = np.full(5, 1j, dtype=complex)
|
274
279
|
Aexpm = scipy.sparse.diags_array(np.exp(np.arange(5)),format='csr')
|
275
280
|
assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B))
|
281
|
+
BI = np.identity(5, dtype=complex)*1j
|
282
|
+
assert_allclose(
|
283
|
+
np.diag(expm_multiply(A, scipy.sparse.csr_array(BI), 0, 1)[-1]),
|
284
|
+
Aexpm.dot(B)
|
285
|
+
)
|
276
286
|
|
277
287
|
def test_expm_multiply_interval_status_0(self):
|
278
288
|
self._help_test_specific_expm_interval_status(0)
|
@@ -13,6 +13,7 @@ import scipy.sparse as sparse
|
|
13
13
|
|
14
14
|
import scipy.sparse.linalg._interface as interface
|
15
15
|
from scipy.sparse._sputils import matrix
|
16
|
+
from scipy._lib._gcutils import assert_deallocated, IS_PYPY
|
16
17
|
|
17
18
|
|
18
19
|
class TestLinearOperator:
|
@@ -512,6 +513,30 @@ def test_transpose_noconjugate():
|
|
512
513
|
assert_equal(B.dot(v), Y.dot(v))
|
513
514
|
assert_equal(B.T.dot(v), Y.T.dot(v))
|
514
515
|
|
516
|
+
def test_transpose_multiplication():
|
517
|
+
class MyMatrix(interface.LinearOperator):
|
518
|
+
def __init__(self, A):
|
519
|
+
super().__init__(A.dtype, A.shape)
|
520
|
+
self.A = A
|
521
|
+
def _matmat(self, other): return self.A @ other
|
522
|
+
def _rmatmat(self, other): return self.A.T @ other
|
523
|
+
|
524
|
+
A = MyMatrix(np.array([[1, 2], [3, 4]]))
|
525
|
+
X = np.array([1, 2])
|
526
|
+
B = np.array([[10, 20], [30, 40]])
|
527
|
+
X2 = X.reshape(-1, 1)
|
528
|
+
Y = np.array([[1, 2], [3, 4]])
|
529
|
+
|
530
|
+
assert_equal(A @ B, Y @ B)
|
531
|
+
assert_equal(B.T @ A, B.T @ Y)
|
532
|
+
assert_equal(A.T @ B, Y.T @ B)
|
533
|
+
assert_equal(A @ X, Y @ X)
|
534
|
+
assert_equal(X.T @ A, X.T @ Y)
|
535
|
+
assert_equal(A.T @ X, Y.T @ X)
|
536
|
+
assert_equal(A @ X2, Y @ X2)
|
537
|
+
assert_equal(X2.T @ A, X2.T @ Y)
|
538
|
+
assert_equal(A.T @ X2, Y.T @ X2)
|
539
|
+
|
515
540
|
def test_sparse_matmat_exception():
|
516
541
|
A = interface.LinearOperator((2, 2), matvec=lambda x: x)
|
517
542
|
B = sparse.eye_array(2)
|
@@ -524,3 +549,13 @@ def test_sparse_matmat_exception():
|
|
524
549
|
A @ np.identity(4)
|
525
550
|
with assert_raises(ValueError):
|
526
551
|
np.identity(4) @ A
|
552
|
+
|
553
|
+
|
554
|
+
@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy")
|
555
|
+
def test_MatrixLinearOperator_refcycle():
|
556
|
+
# gh-10634
|
557
|
+
# Test that MatrixLinearOperator can be automatically garbage collected
|
558
|
+
A = np.eye(2)
|
559
|
+
with assert_deallocated(interface.MatrixLinearOperator, A) as op:
|
560
|
+
op.adjoint()
|
561
|
+
del op
|
@@ -239,6 +239,10 @@ def test_expm_multiply(matrices):
|
|
239
239
|
x = splin.expm_multiply(A_sparse, b)
|
240
240
|
assert_allclose(x, x0)
|
241
241
|
|
242
|
+
x0 = splin.expm_multiply(A_dense, A_dense)
|
243
|
+
x = splin.expm_multiply(A_sparse, A_sparse)
|
244
|
+
assert_allclose(x.todense(), x0)
|
245
|
+
|
242
246
|
|
243
247
|
def test_eq(same_matrix):
|
244
248
|
sp_sparse, pd_sparse = same_matrix
|
scipy/sparse/tests/test_base.py
CHANGED
@@ -1087,6 +1087,12 @@ class _TestCommon:
|
|
1087
1087
|
datsp.sum(axis=1, out=datsp_out)
|
1088
1088
|
assert_array_almost_equal(dat_out, datsp_out)
|
1089
1089
|
|
1090
|
+
# check that wrong shape out parameter raises
|
1091
|
+
with assert_raises(ValueError, match="output parameter.*wrong.*dimension"):
|
1092
|
+
datsp.sum(out=array([0]))
|
1093
|
+
with assert_raises(ValueError, match="output parameter.*wrong.*dimension"):
|
1094
|
+
datsp.sum(out=array([[0]] if self.is_array_test else 0))
|
1095
|
+
|
1090
1096
|
def test_numpy_sum(self):
|
1091
1097
|
# See gh-5987
|
1092
1098
|
dat = array([[0, 1, 2],
|
@@ -1184,6 +1190,12 @@ class _TestCommon:
|
|
1184
1190
|
datsp.mean(axis=1, out=datsp_out)
|
1185
1191
|
assert_array_almost_equal(dat_out, datsp_out)
|
1186
1192
|
|
1193
|
+
# check that wrong shape out parameter raises
|
1194
|
+
with assert_raises(ValueError, match="output parameter.*wrong.*dimension"):
|
1195
|
+
datsp.mean(out=array([0]))
|
1196
|
+
with assert_raises(ValueError, match="output parameter.*wrong.*dimension"):
|
1197
|
+
datsp.mean(out=array([[0]] if self.is_array_test else 0))
|
1198
|
+
|
1187
1199
|
def test_numpy_mean(self):
|
1188
1200
|
# See gh-5987
|
1189
1201
|
dat = array([[0, 1, 2],
|
@@ -142,7 +142,7 @@ class TestCommon1D:
|
|
142
142
|
datsp.sum(axis=(0, 1))
|
143
143
|
with pytest.raises(TypeError, match='axis must be an integer'):
|
144
144
|
datsp.sum(axis=1.5)
|
145
|
-
with pytest.raises(ValueError, match='
|
145
|
+
with pytest.raises(ValueError, match='output parameter.*wrong.*dimension'):
|
146
146
|
datsp.sum(axis=0, out=out)
|
147
147
|
|
148
148
|
def test_numpy_sum(self, spcreator):
|
@@ -180,7 +180,7 @@ class TestCommon1D:
|
|
180
180
|
datsp.mean(axis=(0, 1))
|
181
181
|
with pytest.raises(TypeError, match='axis must be an integer'):
|
182
182
|
datsp.mean(axis=1.5)
|
183
|
-
with pytest.raises(ValueError, match='
|
183
|
+
with pytest.raises(ValueError, match='output parameter.*wrong.*dimension'):
|
184
184
|
datsp.mean(axis=1, out=out)
|
185
185
|
|
186
186
|
def test_sum_dtype(self, spcreator):
|
@@ -209,17 +209,22 @@ class TestCommon1D:
|
|
209
209
|
dat = np.array([0, 1, 2])
|
210
210
|
datsp = spcreator(dat)
|
211
211
|
|
212
|
-
dat_out = np.array(
|
213
|
-
datsp_out = np.array(
|
212
|
+
dat_out = np.array(0)
|
213
|
+
datsp_out = np.array(0)
|
214
214
|
|
215
|
-
dat.mean(out=dat_out
|
215
|
+
dat.mean(out=dat_out)
|
216
216
|
datsp.mean(out=datsp_out)
|
217
217
|
assert_allclose(dat_out, datsp_out)
|
218
218
|
|
219
|
-
dat.mean(axis=0, out=dat_out
|
219
|
+
dat.mean(axis=0, out=dat_out)
|
220
220
|
datsp.mean(axis=0, out=datsp_out)
|
221
221
|
assert_allclose(dat_out, datsp_out)
|
222
222
|
|
223
|
+
with pytest.raises(ValueError, match="output parameter.*dimension"):
|
224
|
+
datsp.mean(out=np.array([0]))
|
225
|
+
with pytest.raises(ValueError, match="output parameter.*dimension"):
|
226
|
+
datsp.mean(out=np.array([[0]]))
|
227
|
+
|
223
228
|
def test_numpy_mean(self, spcreator):
|
224
229
|
dat = np.array([0, 1, 2])
|
225
230
|
datsp = spcreator(dat)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1181,6 +1181,105 @@ class Test_HalfspaceIntersection:
|
|
1181
1181
|
|
1182
1182
|
assert_allclose(hs.dual_points, qhalf_points)
|
1183
1183
|
|
1184
|
+
@pytest.mark.parametrize("k", range(1,4))
|
1185
|
+
def test_halfspace_batch(self, k):
|
1186
|
+
# Test that we can add halfspaces a few at a time
|
1187
|
+
big_square = np.array([[ 1., 0., -2.],
|
1188
|
+
[-1., 0., -2.],
|
1189
|
+
[ 0., 1., -2.],
|
1190
|
+
[ 0., -1., -2.]])
|
1191
|
+
|
1192
|
+
small_square = np.array([[ 1., 0., -1.],
|
1193
|
+
[-1., 0., -1.],
|
1194
|
+
[ 0., 1., -1.],
|
1195
|
+
[ 0., -1., -1.]])
|
1196
|
+
|
1197
|
+
hs = qhull.HalfspaceIntersection(big_square,
|
1198
|
+
np.array([0.3141, 0.2718]),
|
1199
|
+
incremental=True)
|
1200
|
+
|
1201
|
+
hs.add_halfspaces(small_square[0:k,:])
|
1202
|
+
hs.add_halfspaces(small_square[k:4,:])
|
1203
|
+
hs.close()
|
1204
|
+
|
1205
|
+
# Check the intersections are correct (they are the corners of the small square)
|
1206
|
+
expected_intersections = np.array([[1., 1.],
|
1207
|
+
[1., -1.],
|
1208
|
+
[-1., 1.],
|
1209
|
+
[-1., -1.]])
|
1210
|
+
actual_intersections = hs.intersections
|
1211
|
+
# They may be in any order, so just check that under some permutation
|
1212
|
+
# expected=actual.
|
1213
|
+
|
1214
|
+
ind1 = np.lexsort((actual_intersections[:, 1], actual_intersections[:, 0]))
|
1215
|
+
ind2 = np.lexsort((expected_intersections[:, 1], expected_intersections[:, 0]))
|
1216
|
+
assert_allclose(actual_intersections[ind1], expected_intersections[ind2])
|
1217
|
+
|
1218
|
+
|
1219
|
+
@pytest.mark.parametrize("halfspaces", [
|
1220
|
+
(np.array([-0.70613882, -0.45589431, 0.04178256])),
|
1221
|
+
(np.array([[-0.70613882, -0.45589431, 0.04178256],
|
1222
|
+
[0.70807342, -0.45464871, -0.45969769],
|
1223
|
+
[0., 0.76515026, -0.35614825]])),
|
1224
|
+
])
|
1225
|
+
def test_gh_19865(self, halfspaces):
|
1226
|
+
# starting off with a feasible interior point and
|
1227
|
+
# adding halfspaces for which it is no longer feasible
|
1228
|
+
# should result in an error rather than a problematic
|
1229
|
+
# intersection polytope
|
1230
|
+
initial_square = np.array(
|
1231
|
+
[[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]]
|
1232
|
+
)
|
1233
|
+
incremental_intersector = qhull.HalfspaceIntersection(initial_square,
|
1234
|
+
np.zeros(2),
|
1235
|
+
incremental=True)
|
1236
|
+
with pytest.raises(qhull.QhullError, match="feasible.*-0.706.*"):
|
1237
|
+
incremental_intersector.add_halfspaces(halfspaces)
|
1238
|
+
|
1239
|
+
|
1240
|
+
def test_gh_19865_3d(self):
|
1241
|
+
# 3d case where closed half space is enforced for
|
1242
|
+
# feasibility
|
1243
|
+
halfspaces = np.array([[1, 1, 1, -1], # doesn't exclude origin
|
1244
|
+
[-1, -1, -1, -1], # doesn't exclude origin
|
1245
|
+
[1, 0, 0, 0]]) # the origin is on the line
|
1246
|
+
initial_cube = np.array([[1, 0, 0, -1],
|
1247
|
+
[-1, 0, 0, -1],
|
1248
|
+
[0, 1, 0, -1],
|
1249
|
+
[0, -1, 0, -1],
|
1250
|
+
[0, 0, 1, -1],
|
1251
|
+
[0, 0, -1, -1]])
|
1252
|
+
incremental_intersector = qhull.HalfspaceIntersection(initial_cube,
|
1253
|
+
np.zeros(3),
|
1254
|
+
incremental=True)
|
1255
|
+
with pytest.raises(qhull.QhullError, match="feasible.*[1 0 0 0]"):
|
1256
|
+
incremental_intersector.add_halfspaces(halfspaces)
|
1257
|
+
|
1258
|
+
|
1259
|
+
def test_2d_add_halfspace_input(self):
|
1260
|
+
# incrementally added halfspaces should respect the 2D
|
1261
|
+
# array shape requirement
|
1262
|
+
initial_square = np.array(
|
1263
|
+
[[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]]
|
1264
|
+
)
|
1265
|
+
incremental_intersector = qhull.HalfspaceIntersection(initial_square,
|
1266
|
+
np.zeros(2),
|
1267
|
+
incremental=True)
|
1268
|
+
with pytest.raises(ValueError, match="2D array"):
|
1269
|
+
incremental_intersector.add_halfspaces(np.ones((4, 4, 4)))
|
1270
|
+
|
1271
|
+
def test_1d_add_halfspace_input(self):
|
1272
|
+
# we do allow 1D `halfspaces` input to add_halfspaces()
|
1273
|
+
initial_square = np.array(
|
1274
|
+
[[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]]
|
1275
|
+
)
|
1276
|
+
incremental_intersector = qhull.HalfspaceIntersection(initial_square,
|
1277
|
+
np.zeros(2),
|
1278
|
+
incremental=True)
|
1279
|
+
assert_allclose(incremental_intersector.dual_vertices, np.arange(4))
|
1280
|
+
incremental_intersector.add_halfspaces(np.array([2, 2, -1]))
|
1281
|
+
assert_allclose(incremental_intersector.dual_vertices, np.arange(5))
|
1282
|
+
|
1184
1283
|
|
1185
1284
|
@pytest.mark.parametrize("diagram_type", [Voronoi, qhull.Delaunay])
|
1186
1285
|
def test_gh_20623(diagram_type):
|
Binary file
|
Binary file
|
@@ -168,10 +168,6 @@ def test_from_quat_wrong_shape():
|
|
168
168
|
[[4, 5, 6, 7]]
|
169
169
|
]))
|
170
170
|
|
171
|
-
# 0-length 2d array
|
172
|
-
with pytest.raises(ValueError, match='Expected `quat` to have shape'):
|
173
|
-
Rotation.from_quat(np.array([]).reshape((0, 4)))
|
174
|
-
|
175
171
|
|
176
172
|
def test_zero_norms_from_quat():
|
177
173
|
x = np.array([
|
@@ -1611,18 +1607,23 @@ def test_slerp_rot_is_rotation():
|
|
1611
1607
|
t = np.array([0, 1])
|
1612
1608
|
Slerp(t, r)
|
1613
1609
|
|
1610
|
+
SLERP_EXCEPTION_MESSAGE = "must be a sequence of at least 2 rotations"
|
1614
1611
|
|
1615
1612
|
def test_slerp_single_rot():
|
1616
|
-
|
1617
|
-
with pytest.raises(ValueError, match=
|
1618
|
-
r = Rotation.from_quat([1, 2, 3, 4])
|
1613
|
+
r = Rotation.from_quat([1, 2, 3, 4])
|
1614
|
+
with pytest.raises(ValueError, match=SLERP_EXCEPTION_MESSAGE):
|
1619
1615
|
Slerp([1], r)
|
1620
1616
|
|
1621
1617
|
|
1618
|
+
def test_slerp_rot_len0():
|
1619
|
+
r = Rotation.random()
|
1620
|
+
with pytest.raises(ValueError, match=SLERP_EXCEPTION_MESSAGE):
|
1621
|
+
Slerp([], r)
|
1622
|
+
|
1623
|
+
|
1622
1624
|
def test_slerp_rot_len1():
|
1623
|
-
|
1624
|
-
with pytest.raises(ValueError, match=
|
1625
|
-
r = Rotation.from_quat([[1, 2, 3, 4]])
|
1625
|
+
r = Rotation.random(1)
|
1626
|
+
with pytest.raises(ValueError, match=SLERP_EXCEPTION_MESSAGE):
|
1626
1627
|
Slerp([1], r)
|
1627
1628
|
|
1628
1629
|
|
@@ -2015,3 +2016,173 @@ def test_compare_as_davenport_as_euler():
|
|
2015
2016
|
eul = rot.as_euler(seq)
|
2016
2017
|
dav = rot.as_davenport(ax, order)
|
2017
2018
|
assert_allclose(eul, dav, rtol=1e-12)
|
2019
|
+
|
2020
|
+
|
2021
|
+
def test_zero_rotation_construction():
|
2022
|
+
r = Rotation.random(num=0)
|
2023
|
+
assert len(r) == 0
|
2024
|
+
|
2025
|
+
r_ide = Rotation.identity(num=0)
|
2026
|
+
assert len(r_ide) == 0
|
2027
|
+
|
2028
|
+
r_get = Rotation.random(num=3)[[]]
|
2029
|
+
assert len(r_get) == 0
|
2030
|
+
|
2031
|
+
r_quat = Rotation.from_quat(np.zeros((0, 4)))
|
2032
|
+
assert len(r_quat) == 0
|
2033
|
+
|
2034
|
+
r_matrix = Rotation.from_matrix(np.zeros((0, 3, 3)))
|
2035
|
+
assert len(r_matrix) == 0
|
2036
|
+
|
2037
|
+
r_euler = Rotation.from_euler("xyz", np.zeros((0, 3)))
|
2038
|
+
assert len(r_euler) == 0
|
2039
|
+
|
2040
|
+
r_vec = Rotation.from_rotvec(np.zeros((0, 3)))
|
2041
|
+
assert len(r_vec) == 0
|
2042
|
+
|
2043
|
+
r_dav = Rotation.from_davenport(np.eye(3), "extrinsic", np.zeros((0, 3)))
|
2044
|
+
assert len(r_dav) == 0
|
2045
|
+
|
2046
|
+
r_mrp = Rotation.from_mrp(np.zeros((0, 3)))
|
2047
|
+
assert len(r_mrp) == 0
|
2048
|
+
|
2049
|
+
|
2050
|
+
def test_zero_rotation_representation():
|
2051
|
+
r = Rotation.random(num=0)
|
2052
|
+
assert r.as_quat().shape == (0, 4)
|
2053
|
+
assert r.as_matrix().shape == (0, 3, 3)
|
2054
|
+
assert r.as_euler("xyz").shape == (0, 3)
|
2055
|
+
assert r.as_rotvec().shape == (0, 3)
|
2056
|
+
assert r.as_mrp().shape == (0, 3)
|
2057
|
+
assert r.as_davenport(np.eye(3), "extrinsic").shape == (0, 3)
|
2058
|
+
|
2059
|
+
|
2060
|
+
def test_zero_rotation_array_rotation():
|
2061
|
+
r = Rotation.random(num=0)
|
2062
|
+
|
2063
|
+
v = np.array([1, 2, 3])
|
2064
|
+
v_rotated = r.apply(v)
|
2065
|
+
assert v_rotated.shape == (0, 3)
|
2066
|
+
|
2067
|
+
v0 = np.zeros((0, 3))
|
2068
|
+
v0_rot = r.apply(v0)
|
2069
|
+
assert v0_rot.shape == (0, 3)
|
2070
|
+
|
2071
|
+
v2 = np.ones((2, 3))
|
2072
|
+
with pytest.raises(
|
2073
|
+
ValueError, match="Expected equal numbers of rotations and vectors"):
|
2074
|
+
r.apply(v2)
|
2075
|
+
|
2076
|
+
|
2077
|
+
def test_zero_rotation_multiplication():
|
2078
|
+
r = Rotation.random(num=0)
|
2079
|
+
|
2080
|
+
r_single = Rotation.random()
|
2081
|
+
r_mult_left = r * r_single
|
2082
|
+
assert len(r_mult_left) == 0
|
2083
|
+
|
2084
|
+
r_mult_right = r_single * r
|
2085
|
+
assert len(r_mult_right) == 0
|
2086
|
+
|
2087
|
+
r0 = Rotation.random(0)
|
2088
|
+
r_mult = r * r0
|
2089
|
+
assert len(r_mult) == 0
|
2090
|
+
|
2091
|
+
msg_rotation_error = "Expected equal number of rotations"
|
2092
|
+
r2 = Rotation.random(2)
|
2093
|
+
with pytest.raises(ValueError, match=msg_rotation_error):
|
2094
|
+
r0 * r2
|
2095
|
+
|
2096
|
+
with pytest.raises(ValueError, match=msg_rotation_error):
|
2097
|
+
r2 * r0
|
2098
|
+
|
2099
|
+
|
2100
|
+
def test_zero_rotation_concatentation():
|
2101
|
+
r = Rotation.random(num=0)
|
2102
|
+
|
2103
|
+
r0 = Rotation.concatenate([r, r])
|
2104
|
+
assert len(r0) == 0
|
2105
|
+
|
2106
|
+
r1 = r.concatenate([Rotation.random(), r])
|
2107
|
+
assert len(r1) == 1
|
2108
|
+
|
2109
|
+
r3 = r.concatenate([Rotation.random(3), r])
|
2110
|
+
assert len(r3) == 3
|
2111
|
+
|
2112
|
+
r4 = r.concatenate([r, Rotation.random(4)])
|
2113
|
+
assert len(r4) == 4
|
2114
|
+
|
2115
|
+
|
2116
|
+
def test_zero_rotation_power():
|
2117
|
+
r = Rotation.random(num=0)
|
2118
|
+
for pp in [-1.5, -1, 0, 1, 1.5]:
|
2119
|
+
pow0 = r**pp
|
2120
|
+
assert len(pow0) == 0
|
2121
|
+
|
2122
|
+
|
2123
|
+
def test_zero_rotation_inverse():
|
2124
|
+
r = Rotation.random(num=0)
|
2125
|
+
r_inv = r.inv()
|
2126
|
+
assert len(r_inv) == 0
|
2127
|
+
|
2128
|
+
|
2129
|
+
def test_zero_rotation_magnitude():
|
2130
|
+
r = Rotation.random(num=0)
|
2131
|
+
magnitude = r.magnitude()
|
2132
|
+
assert magnitude.shape == (0,)
|
2133
|
+
|
2134
|
+
|
2135
|
+
def test_zero_rotation_mean():
|
2136
|
+
r = Rotation.random(num=0)
|
2137
|
+
with pytest.raises(ValueError, match="Mean of an empty rotation set is undefined."):
|
2138
|
+
r.mean()
|
2139
|
+
|
2140
|
+
|
2141
|
+
def test_zero_rotation_approx_equal():
|
2142
|
+
r = Rotation.random(0)
|
2143
|
+
assert r.approx_equal(Rotation.random(0)).shape == (0,)
|
2144
|
+
assert r.approx_equal(Rotation.random()).shape == (0,)
|
2145
|
+
assert Rotation.random().approx_equal(r).shape == (0,)
|
2146
|
+
|
2147
|
+
approx_msg = "Expected equal number of rotations"
|
2148
|
+
r3 = Rotation.random(2)
|
2149
|
+
with pytest.raises(ValueError, match=approx_msg):
|
2150
|
+
r.approx_equal(r3)
|
2151
|
+
|
2152
|
+
with pytest.raises(ValueError, match=approx_msg):
|
2153
|
+
r3.approx_equal(r)
|
2154
|
+
|
2155
|
+
|
2156
|
+
def test_zero_rotation_get_set():
|
2157
|
+
r = Rotation.random(0)
|
2158
|
+
|
2159
|
+
r_get = r[[]]
|
2160
|
+
assert len(r_get) == 0
|
2161
|
+
|
2162
|
+
r_slice = r[:0]
|
2163
|
+
assert len(r_slice) == 0
|
2164
|
+
|
2165
|
+
with pytest.raises(IndexError):
|
2166
|
+
r[[0]]
|
2167
|
+
|
2168
|
+
with pytest.raises(IndexError):
|
2169
|
+
r[[True]]
|
2170
|
+
|
2171
|
+
with pytest.raises(IndexError):
|
2172
|
+
r[0] = Rotation.random()
|
2173
|
+
|
2174
|
+
|
2175
|
+
def test_boolean_indexes():
|
2176
|
+
r = Rotation.random(3)
|
2177
|
+
|
2178
|
+
r0 = r[[False, False, False]]
|
2179
|
+
assert len(r0) == 0
|
2180
|
+
|
2181
|
+
r1 = r[[False, True, False]]
|
2182
|
+
assert len(r1) == 1
|
2183
|
+
|
2184
|
+
r3 = r[[True, True, True]]
|
2185
|
+
assert len(r3) == 3
|
2186
|
+
|
2187
|
+
with pytest.raises(IndexError):
|
2188
|
+
r[[True, True]]
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|