53
53
54
54
import math
55
55
import numpy as np
56
- from numpy import any , array , asarray , concatenate , cos , delete , \
57
- dot , empty , exp , eye , isinf , ones , pad , sin , zeros , squeeze , pi
56
+ from numpy import any , asarray , concatenate , cos , delete , \
57
+ dot , empty , exp , eye , isinf , ones , pad , sin , zeros , squeeze
58
58
from numpy .random import rand , randn
59
- from numpy .linalg import solve , eigvals , matrix_rank
59
+ from numpy .linalg import eigvals , lstsq , matrix_rank , solve
60
60
from numpy .linalg .linalg import LinAlgError
61
61
import scipy as sp
62
62
from scipy .signal import cont2discrete
@@ -887,6 +887,8 @@ def horner(self, x, warn_infinite=True):
887
887
"""
888
888
# Make sure the argument is a 1D array of complex numbers
889
889
x_arr = np .atleast_1d (x ).astype (complex , copy = False )
890
+ if len (x_arr .shape ) > 1 :
891
+ raise ValueError ("input list must be 1D" )
890
892
891
893
# return fast on systems with 0 or 1 state
892
894
if not config .defaults ['statesp.use_numpy_matrix' ]:
@@ -908,21 +910,21 @@ def horner(self, x, warn_infinite=True):
908
910
# Fall back because either Slycot unavailable or cannot handle
909
911
# certain cases.
910
912
911
- # Make sure that we are operating on a simple list
912
- if len (x_arr .shape ) > 1 :
913
- raise ValueError ("input list must be 1D" )
914
-
915
913
# Preallocate
916
914
out = empty ((self .noutputs , self .ninputs , len (x_arr )),
917
915
dtype = complex )
918
916
919
917
# TODO: can this be vectorized?
920
918
for idx , x_idx in enumerate (x_arr ):
921
919
try :
922
- out [:, :, idx ] = np .dot (
923
- self .C ,
924
- solve (x_idx * eye (self .nstates ) - self .A , self .B )) \
925
- + self .D
920
+ xI_A = x_idx * eye (self .nstates ) - self .A
921
+ xI_A_inv = solve (xI_A , self .B )
922
+ # gh-664: not singular but the underlying LAPACK routine
923
+ # was not satisfied with the condition. Try least-squares
924
+ # solver.
925
+ if np .any (np .isnan (xI_A_inv )): # pragma: no cover
926
+ xI_A_inv , _ , _ , _ = lstsq (xI_A , self .B , rcond = None )
927
+ out [:, :, idx ] = np .dot (self .C , xI_A_inv ) + self .D
926
928
except LinAlgError :
927
929
# Issue a warning messsage, for consistency with xferfcn
928
930
if warn_infinite :
@@ -936,6 +938,8 @@ def horner(self, x, warn_infinite=True):
936
938
else :
937
939
out [:, :, idx ] = complex (np .inf , np .nan )
938
940
941
+
942
+
939
943
return out
940
944
941
945
def freqresp (self , omega ):
0 commit comments